// import com.alibaba.druid.DbType;
// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.expr.*;
// import com.alibaba.druid.sql.ast.statement.*;
// import com.alibaba.druid.sql.dialect.mysql.ast.*;
// import com.alibaba.druid.sql.dialect.mysql.ast.clause.*;
// import com.alibaba.druid.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType;
// import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;
// import com.alibaba.druid.sql.dialect.mysql.ast.expr.*;
// import com.alibaba.druid.sql.dialect.mysql.ast.statement.*;
// import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;
// import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification;
// import com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;
// import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
// import com.alibaba.druid.sql.visitor.VisitorFeature;
// import com.alibaba.druid.util.FnvHash;

// import java.io.IOException;
// import java.security.AccessControlException;
// import java.util.ArrayList;
// import java.util.List;
// import java.util.Map;
#include "MySqlOutputVisitor.h"
#include "../../../ast/expr/SQLIdentifierExpr.h"
#include "../../../../utils/log.h"
#include "../../../../utils/instanceof.h"
#include "../../../../DbType.h"

BOOL_ptr MySqlOutputVisitor::shardingSupportChecked = BOOL::FALSE;

MySqlOutputVisitor::MySqlOutputVisitor(std::stringstream *appender)
    : SQLASTOutputVisitor(appender)
{
  this->dbType = DbType_ptr(new DbType(&DbType::mysql));
  this->shardingSupport = true;
  this->quote = '`';
}

MySqlOutputVisitor::MySqlOutputVisitor(std::stringstream *appender, BOOL_ptr parameterized)
    : SQLASTOutputVisitor(appender, parameterized)
{

  try
  {
    configFromProperty();
    // } catch (AccessControlException e) {
  }
  catch (...)
  {
    // skip
    LOG_INFO << "catch";
  }
  this->dbType = DbType_ptr(new DbType(&DbType::mysql));
  this->shardingSupport = true;
  this->quote = '`';
}

void MySqlOutputVisitor::configFromProperty()
{
  if (this->parameterized && !shardingSupportChecked)
  {
    shardingSupportChecked = BOOL::TRUE;

    // string_ptr  property = System.getProperties().getProperty("fastsql.parameterized.shardingSupport");
    // if ("BOOL::TRUE".equals(property)) {
    //     this->setShardingSupport(BOOL::TRUE);
    // } else if ("BOOL::FALSE".equals(property)) {
    //     this->setShardingSupport(BOOL::FALSE);
    // }
  }
}

bool MySqlOutputVisitor::isShardingSupport()
{
  return this->parameterized && shardingSupport;
}

void MySqlOutputVisitor::setShardingSupport(bool shardingSupport)
{
  this->shardingSupport = shardingSupport;
}

//     // @Override
//     BOOL_ptr visit(SQLSelectQueryBlock select) {
//         if (select instanceof MySqlSelectQueryBlock) {
//             return visit((MySqlSelectQueryBlock) select);
//         }

//         return super.visit(select);
//     }

//     BOOL_ptr visit(MySqlSelectQueryBlock x) {
//         BOOL_ptr bracket = x.isParenthesized();
//         if (bracket) {
//             print('(');
//         }

//         if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {
//             printlnComments(x.getBeforeCommentsDirect());
//         }

//         string_ptr  cachedSelectList = x.getCachedSelectList();

//         if (cachedSelectList != nullptr) {
//             if (!isEnabled(VisitorFeature.OutputSkipSelectListCacheString)) {
//                 print0(cachedSelectList);
//             }
//         } else {
//             print0(ucase ? "SELECT " : "select ");

//             for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
//                 SQLCommentHint hint = x.getHints().get(i);
//                 hint.accept(this);
//                 print(' ');
//             }

//             switch (x.getDistionOption()) {
//                 case SQLSetQuantifier.ALL:
//                     print0(ucase ? "ALL " : "all ");
//                     break;
//                 case SQLSetQuantifier.DISTINCT:
//                     print0(ucase ? "DISTINCT " : "distinct ");
//                     break;
//                 case SQLSetQuantifier.DISTINCTROW:
//                     print0(ucase ? "DISTINCTROW " : "distinctrow ");
//                     break;
//                 case SQLSetQuantifier.UNIQUE:
//                     print0(ucase ? "UNIQUE " : "unique ");
//                     break;
//                 default:
//                     break;
//             }

//             if (x.isHignPriority()) {
//                 print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
//             }

//             if (x.isStraightJoin()) {
//                 print0(ucase ? "STRAIGHT_JOIN " : "straight_join ");
//             }

//             if (x.isSmallResult()) {
//                 print0(ucase ? "SQL_SMALL_RESULT " : "sql_small_result ");
//             }

//             if (x.isBigResult()) {
//                 print0(ucase ? "SQL_BIG_RESULT " : "sql_big_result ");
//             }

//             if (x.isBufferResult()) {
//                 print0(ucase ? "SQL_BUFFER_RESULT " : "sql_buffer_result ");
//             }

//             if (x.getCache() != nullptr) {
//                 if (x.getCache().booleanValue()) {
//                     print0(ucase ? "SQL_CACHE " : "sql_cache ");
//                 } else {
//                     print0(ucase ? "SQL_NO_CACHE " : "sql_no_cache ");
//                 }
//             }

//             if (x.isCalcFoundRows()) {
//                 print0(ucase ? "SQL_CALC_FOUND_ROWS " : "sql_calc_found_rows ");
//             }

//             printSelectList(x.getSelectList());

//             SQLName forcePartition = x.getForcePartition();
//             if (forcePartition != nullptr) {
//                 println();
//                 print0(ucase ? "FORCE PARTITION " : "force partition ");
//                 printExpr(forcePartition, parameterized);
//             }

//             SQLExprTableSource into = x.getInto();
//             if (into != nullptr) {
//                 println();
//                 print0(ucase ? "INTO " : "into ");
//                 printTableSource(into);
//             }
//         }

//         SQLTableSource from = x.getFrom();
//         if (from != nullptr) {
//             println();
//             print0(ucase ? "FROM " : "from ");

//             printTableSource(from);
//         }

//         SQLExpr where = x.getWhere();
//         if (where != nullptr) {
//             printWhere(where);
//         }

//         printHierarchical(x);

//         SQLSelectGroupByClause groupBy = x.getGroupBy();
//         if (groupBy != nullptr) {
//             println();
//             visit(groupBy);
//         }

//         List<SQLWindow> windows = x.getWindows();
//         if (windows != nullptr && windows.size() > 0) {
//             println();
//             print0(ucase ? "WINDOW " : "window ");
//             printAndAccept(windows, ", ");
//         }

//         SQLOrderBy orderBy = x.getOrderBy();
//         if (orderBy != nullptr) {
//             println();
//             visit(orderBy);
//         }

//         SQLLimit limit = x.getLimit();
//         if (limit != nullptr) {
//             println();
//             visit(limit);
//         }

//         SQLName procedureName = x.getProcedureName();
//         if (procedureName != nullptr) {
//             print0(ucase ? " PROCEDURE " : " procedure ");
//             procedureName.accept(this);
//             if (!x.getProcedureArgumentList().isEmpty()) {
//                 print('(');
//                 printAndAccept(x.getProcedureArgumentList(), ", ");
//                 print(')');
//             }
//         }

//         if (x.isForUpdate()) {
//             println();
//             print0(ucase ? "FOR UPDATE" : "for update");
//             if (x.isNoWait()) {
//                 print0(ucase ? " NOWAIT" : " nowait");
//             } else if (x.getWaitTime() != nullptr) {
//                 print0(ucase ? " WAIT " : " wait ");
//                 x.getWaitTime().accept(this);
//             }

//             if (x.isSkipLocked()) {
//                 print0(ucase ? " SKIP LOCKED" : " skip locked");
//             }
//         }

//         if (x.isForShare()) {
//             println();
//             print0(ucase ? "FOR SHARE" : "for share");
//         }

//         if (x.isLockInShareMode()) {
//             println();
//             print0(ucase ? "LOCK IN SHARE MODE" : "lock in share mode");
//         }

//         if (bracket) {
//             print(')');
//         }

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLColumnDefinition x) {
//         BOOL_ptr parameterized = this->parameterized;
//         this->parameterized = BOOL::FALSE;

//         x.getName().accept(this);

//         SQLDataType dataType = x.getDataType();
//         if (dataType != nullptr) {
//             print(' ');
//             dataType.accept(this);
//         }

//         SQLExpr generatedAlawsAs = x.getGeneratedAlawsAs();
//         if (generatedAlawsAs != nullptr) {
//             print0(ucase ? " GENERATED ALWAYS AS (" : " generated always as (");
//             printExpr(generatedAlawsAs);
//             print(')');
//         }

//         if (x.isVirtual()) {
//             print0(ucase ? " VIRTUAL" : " virtual");
//         }

//         if (x.isVisible()) {
//             print0(ucase ? " VISIBLE" : " visible");
//         }

//         SQLExpr charsetExpr = x.getCharsetExpr();
//         if (charsetExpr != nullptr) {
//             print0(ucase ? " CHARACTER SET " : " character set ");
//             charsetExpr.accept(this);
//         }

//         SQLExpr collateExpr = x.getCollateExpr();
//         if (collateExpr != nullptr) {
//             print0(ucase ? " COLLATE " : " collate ");
//             collateExpr.accept(this);
//         }

//         for (SQLColumnConstraint item : x.getConstraints()) {
//             if (item instanceof SQLColumnReference) {
//                 continue;
//             }
//             print(' ');
//             item.accept(this);
//         }

//         SQLExpr defaultExpr = x.getDefaultExpr();
//         if (defaultExpr != nullptr) {
//             print0(ucase ? " DEFAULT " : " default ");
//             defaultExpr.accept(this);
//         }

//         SQLExpr storage = x.getStorage();
//         if (storage != nullptr) {
//             print0(ucase ? " STORAGE " : " storage ");
//             storage.accept(this);
//         }

//         SQLExpr format = x.getFormat();
//         if (format != nullptr) {
//             printUcase(" COLUMN_FORMAT ");
//             format.accept(this);
//         }

//         SQLExpr onUpdate = x.getOnUpdate();
//         if (onUpdate != nullptr) {
//             print0(ucase ? " ON UPDATE " : " on update ");

//             onUpdate.accept(this);
//         }

//         if (x.getJsonIndexAttrsExpr() != nullptr) {
//             print0(ucase ? " JSONINDEXATTRS '" : " jsonindexattrs '");
//             x.getJsonIndexAttrsExpr().accept(this);
//             print0("' ");
//         }

//         if (x.isAutoIncrement()) {
//             print0(ucase ? " AUTO_INCREMENT" : " auto_increment");
//         }

//         if (x.getDelimiterTokenizer() != nullptr) {
//             print0(ucase ? " DELIMITER_TOKENIZER " : " delimiter_tokenizer ");
//             x.getDelimiterTokenizer().accept(this);
//         }
//         if (x.getNlpTokenizer() != nullptr) {
//             print0(ucase ? " NLP_TOKENIZER " : " nlp_tokenizer ");
//             x.getNlpTokenizer().accept(this);
//         }
//         if (x.getValueType() != nullptr) {
//             print0(ucase ? " VALUE_TYPE " : " value_type ");
//             x.getValueType().accept(this);
//         }

//         AutoIncrementType sequenceType = x.getSequenceType();
//         if (sequenceType != nullptr) {
//             print0(ucase ? " BY " : " by ");
//             print0(ucase ? sequenceType.getKeyword() : sequenceType.getKeyword().toLowerCase());
//         }

//         SQLExpr unitCount = x.getUnitCount();
//         if (unitCount != nullptr) {
//             print0(ucase ? " UNIT COUNT " : " unit count ");
//             printExpr(unitCount);
//         }

//         SQLExpr unitIndex = x.getUnitIndex();
//         if (unitIndex != nullptr) {
//             print0(ucase ? " INDEX " : " index ");
//             printExpr(unitIndex);
//         }

//         if (x.getStep() != nullptr) {
//             print0(ucase ? " STEP " : " STEP ");
//             printExpr(x.getStep());
//         }

//         SQLExpr delimiter = x.getDelimiter();
//         if (delimiter != nullptr) {
//             print0(ucase ? " DELIMITER " : " delimiter ");
//             delimiter.accept(this);
//         }

//         if (x.isDisableIndex() == BOOL::TRUE) {
//             print0(ucase ? " DISABLEINDEX TRUE" : " disableindex BOOL::TRUE");
//         }

//         SQLAnnIndex annIndex = x.getAnnIndex();
//         if (annIndex != nullptr) {
//             print(' ');
//             annIndex.accept(this);
//         }

//         if (x.getComment() != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             x.getComment().accept(this);
//         }

//         if (x.getAsExpr() != nullptr) {
//             print0(ucase ? " AS (" : " as (");
//             x.getAsExpr().accept(this);
//             print(')');
//         }

//         if (x.isStored()) {
//             print0(ucase ? " STORED" : " stored");
//         }

//         if (x.getEncode() != nullptr) {
//             print0(ucase ? " ENCODE=" : " encode=");
//             x.getEncode().accept(this);
//         }

//         if (x.getCompression() != nullptr) {
//             print0(ucase ? " COMPRESSION=" : " compression=");
//             x.getCompression().accept(this);
//         }

//         List<SQLAssignItem> colProperties = x.getColPropertiesDirect();
//         if (colProperties != nullptr && colProperties.size() > 0) {
//             print0(ucase ? " COLPROPERTIES (" : " colproperties (");
//             printAndAccept(colProperties, ", ");
//             print0(ucase ? ")" : ")");
//         }

//         for (SQLColumnConstraint item : x.getConstraints()) {
//             if (item instanceof SQLColumnReference) {
//                 print(' ');
//                 item.accept(this);
//             }
//         }

//         this->parameterized = parameterized;
//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLDataType x) {
//         printDataType(x);

//         if (x instanceof SQLDataTypeImpl) {
//             SQLDataTypeImpl dataTypeImpl = (SQLDataTypeImpl) x;
//             if (dataTypeImpl.isUnsigned()) {
//                 print0(ucase ? " UNSIGNED" : " unsigned");
//             }

//             if (dataTypeImpl.isZerofill()) {
//                 print0(ucase ? " ZEROFILL" : " zerofill");
//             }

//             SQLExpr indexBy = ((SQLDataTypeImpl) x).getIndexBy();
//             if (indexBy != nullptr) {
//                 print0(ucase ? " INDEX BY " : " index by ");
//                 indexBy.accept(this);
//             }
//         }

//         if (x instanceof SQLCharacterDataType) {
//             SQLCharacterDataType charType = (SQLCharacterDataType) x;
//             if (charType.getCharSetName() != nullptr) {
//                 print0(ucase ? " CHARACTER SET " : " character set ");
//                 print0(charType.getCharSetName());

//                 if (charType.getCollate() != nullptr) {
//                     print0(ucase ? " COLLATE " : " collate ");
//                     print0(charType.getCollate());
//                 }
//             }

//             List<SQLCommentHint> hints = ((SQLCharacterDataType) x).hints;
//             if (hints != nullptr) {
//                 print(' ');
//                 for (SQLCommentHint hint : hints) {
//                     hint.accept(this);
//                 }
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLCharacterDataType x) {
//         printDataType(x);

//         if (x.isHasBinary()) {
//             print0(ucase ? " BINARY " : " binary ");
//         }

//         if (x.getCharSetName() != nullptr) {
//             print0(ucase ? " CHARACTER SET " : " character set ");
//             print0(x.getCharSetName());
//             if (x.getCollate() != nullptr) {
//                 print0(ucase ? " COLLATE " : " collate ");
//                 print0(x.getCollate());
//             }
//         } else if (x.getCollate() != nullptr) {
//             print0(ucase ? " COLLATE " : " collate ");
//             print0(x.getCollate());
//         }

//         List<SQLCommentHint> hints = ((SQLCharacterDataType) x).hints;
//         if (hints != nullptr) {
//             print(' ');
//             for (SQLCommentHint hint : hints) {
//                 hint.accept(this);
//             }
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlTableIndex x) {
//         string_ptr  indexType = x.getIndexType();

//         BOOL_ptr indexTypePrinted = BOOL::FALSE;
//         if ("FULLTEXT".equalsIgnoreCase(indexType)) {
//             print0(ucase ? "FULLTEXT " : "fulltext ");
//             indexTypePrinted = BOOL::TRUE;
//         } else if ("SPATIAL".equalsIgnoreCase(indexType)) {
//             print0(ucase ? "SPATIAL " : "spatial ");
//             indexTypePrinted = BOOL::TRUE;
//         } else if ("CLUSTERED".equalsIgnoreCase(indexType)) {
//             print0(ucase ? "CLUSTERED " : "clustered ");
//             indexTypePrinted = BOOL::TRUE;
//         } else if ("CLUSTERING".equalsIgnoreCase(indexType)) {
//             print0(ucase ? "CLUSTERING " : "clustering ");
//             indexTypePrinted = BOOL::TRUE;
//         }

//         if (x.getIndexDefinition().isGlobal()) {
//             print0(ucase ? "GLOBAL " : "global ");
//         } else if (x.getIndexDefinition().isLocal()) {
//             print0(ucase ? "LOCAL " : "local ");
//         }

//         print0(ucase ? "INDEX" : "index");
//         if (x.getName() != nullptr) {
//             print(' ');
//             x.getName().accept(this);
//         }

//         if (indexType != nullptr && !indexTypePrinted) {
//             if ("ANN".equals(indexType)) {
//                 print0(" ");
//                 print0(indexType);
//             }
//         }

//         if (Boolean.TRUE.equals(x.getAttribute("ads.index"))) {
//             if (x.getIndexDefinition().isHashMapType()) {
//                 print0(ucase ? " HASHMAP" : " hashmap");
//             } else if (x.getIndexDefinition().isHashType()) {
//                 print0(ucase ? " HASH" : " hash");
//             }
//         }

//         string_ptr  using = x.getIndexDefinition().hasOptions() ? x.getIndexDefinition().getOptions().getIndexType() : nullptr;
//         if (using != nullptr) {
//             print0(ucase ? " USING " : " using ");
//             print0(using);
//         }

//         print('(');
//         for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
//             if (i != 0) {
//                 print0(", ");
//             }
//             x.getColumns().get(i).accept(this);
//         }
//         print(')');

//         if (x.getAnalyzerName() != nullptr) {
//             print0(ucase ? " WITH ANALYZER " : " with analyzer ");
//             x.getAnalyzerName().accept(this);
//         } else {
//             if (x.getIndexAnalyzerName() != nullptr) {
//                 print0(ucase ? " WITH INDEX ANALYZER " : " with index analyzer ");
//                 x.getIndexAnalyzerName().accept(this);
//             }

//             if (x.getQueryAnalyzerName() != nullptr) {
//                 print0(ucase ? " WITH QUERY ANALYZER " : " with query analyzer ");
//                 x.getQueryAnalyzerName().accept(this);
//             }

//             if (x.getWithDicName() != nullptr) {
//                 printUcase(" WITH DICT ");
//                 x.getWithDicName().accept(this);
//             }
//         }

//         List<SQLName> covering = x.getCovering();
//         if (nullptr != covering && covering.size() > 0) {
//             print0(ucase ? " COVERING " : " covering ");
//             print('(');
//             for (int i = 0, size = covering.size(); i < size; ++i) {
//                 if (i != 0) {
//                     print0(", ");
//                 }
//                 covering.get(i).accept(this);
//             }
//             print(')');
//         }

//         SQLExpr dbPartitionBy = x.getDbPartitionBy();
//         if (dbPartitionBy != nullptr) {
//             print0(ucase ? " DBPARTITION BY " : " dbpartition by ");
//             dbPartitionBy.accept(this);
//         }

//         SQLExpr tablePartitionBy = x.getTablePartitionBy();
//         if (tablePartitionBy != nullptr) {
//             print0(ucase ? " TBPARTITION BY " : " tbpartition by ");
//             tablePartitionBy.accept(this);
//         }

//         SQLExpr tablePartitions = x.getTablePartitions();
//         if (tablePartitions != nullptr) {
//             print0(ucase ? " TBPARTITIONS " : " tbpartitions ");
//             tablePartitions.accept(this);
//         }

//         /*
//         List<SQLAssignItem> options = x.getOptions();
//         if (options.size() > 0) {
//             for (SQLAssignItem option : options) {
//                 print(' ');
//                 option.accept(this);
//             }
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             comment.accept(this);
//         }
//         */
//         if (x.getIndexDefinition().hasOptions()) {
//             x.getIndexDefinition().getOptions().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlKey x) {
//         if (x.isHasConstraint()) {
//             print0(ucase ? "CONSTRAINT " : "constraint ");
//             if (x.getName() != nullptr) {
//                 x.getName().accept(this);
//                 print(' ');
//             }
//         }

//         string_ptr  indexType = x.getIndexType();
//         BOOL_ptr fullText = "FULLTEXT".equalsIgnoreCase(indexType);
//         BOOL_ptr clustering = "CLUSTERING".equalsIgnoreCase(indexType);
//         BOOL_ptr clustered = "CLUSTERED".equalsIgnoreCase(indexType);

//         if (fullText) {
//             print0(ucase ? "FULLTEXT " : "fulltext ");
//         } else if (clustering) {
//             print0(ucase ? "CLUSTERING " : "clustering ");
//         } else if (clustered) {
//             print0(ucase ? "CLUSTERED " : "CLUSTERED ");
//         }

//         print0(ucase ? "KEY" : "key");

//         SQLName name = x.getName();
//         if (name != nullptr) {
//             print(' ');
//             name.accept(this);
//         }

//         if (indexType != nullptr && !fullText && !clustering && !clustered) {
//             print0(ucase ? " USING " : " using ");
//             print0(indexType);
//         }

//         print0(" (");

//         for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
//             if (i != 0) {
//                 print0(", ");
//             }
//             x.getColumns().get(i).accept(this);
//         }
//         print(')');

//         SQLIndexDefinition indexDefinition = x.getIndexDefinition();
//         if (indexDefinition.hasOptions()) {
//             indexDefinition.getOptions().accept(this);
//         }

//         SQLExpr comment = x.getComment();
//         if (indexDefinition.hasOptions()
//                 && indexDefinition.getOptions().getComment() == comment) {
//             comment = nullptr;
//         }

//         if (comment != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             printExpr(comment);
//         }

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLCharExpr x, BOOL_ptr parameterized) {
//         if (this->appender == nullptr) {
//             return BOOL::FALSE;
//         }

//         try {
//             if (parameterized) {
//                 this->appender.append('?');
//                 incrementReplaceCunt();
//                 if (this->parameters != nullptr) {
//                     ExportParameterVisitorUtils.exportParameter(this->parameters, x);
//                 }
//                 return BOOL::FALSE;
//             }

//             this->appender.append('\'');

//             string_ptr  text = x.getText();

//             BOOL_ptr hasSpecial = BOOL::FALSE;
//             for (int i = 0; i < text.length(); ++i) {
//                 char ch = text.charAt(i);
//                 if (ch == '\'' || ch == '\\' || ch == '\0') {
//                     hasSpecial = BOOL::TRUE;
//                     break;
//                 }
//             }

//             if (hasSpecial) {
//                 BOOL_ptr regForPresto = BOOL::FALSE;
//                 if (isEnabled(VisitorFeature.OutputRegForPresto)
//                         && x.getParent() instanceof SQLMethodInvokeExpr) {
//                     SQLMethodInvokeExpr regCall = (SQLMethodInvokeExpr) x.getParent();
//                     long nameHash = regCall.methodNameHashCode64();
//                     regForPresto = (x == regCall.getArguments().get(1))
//                             && (nameHash == FnvHash.Constants.REGEXP_SUBSTR
//                             || nameHash == FnvHash.Constants.REGEXP_COUNT
//                             || nameHash == FnvHash.Constants.REGEXP_EXTRACT
//                             || nameHash == FnvHash.Constants.REGEXP_EXTRACT_ALL
//                             || nameHash == FnvHash.Constants.REGEXP_LIKE
//                             || nameHash == FnvHash.Constants.REGEXP_REPLACE
//                             || nameHash == FnvHash.Constants.REGEXP_SPLIT);
//                 }

//                 for (int i = 0; i < text.length(); ++i) {
//                     char ch = text.charAt(i);
//                     if (ch == '\'') {
//                         appender.append('\'');
//                         appender.append('\'');
//                     } else if (ch == '\\') {
//                         appender.append('\\');
//                         if (regForPresto) {
//                             continue;
//                         }
//                         if (i < text.length() - 1 && text.charAt(i + 1) == '_') {
//                             continue;
//                         }
//                         appender.append('\\');
//                     } else if (ch == '\0') {
//                         appender.append('\\');
//                         appender.append('0');
//                     } else {
//                         appender.append(ch);
//                     }
//                 }
//             } else {
//                 appender.append(text);
//             }

//             appender.append('\'');
//             return BOOL::FALSE;
//         } catch (IOException e) {
//             throw new RuntimeException("println error", e);
//         }
//     }

//     BOOL_ptr visit(SQLVariantRefExpr x) {
//         {
//             int index = x.getIndex();

//             if (inputParameters != nullptr && index < inputParameters.size()) {
//                 return super.visit(x);
//             }
//         }

//         if (x.isGlobal()) {
//             print0("@@global.");
//         } else if (x.isSession()) {
//             print0("@@session.");
//         }

//         string_ptr  varName = x.getName();
//         for (int i = 0; i < varName.length(); ++i) {
//             char ch = varName.charAt(i);
//             if (ch == '\'') {
//                 if (varName.startsWith("@@") && i == 2) {
//                     print(ch);
//                 } else if (varName.startsWith("@") && i == 1) {
//                     print(ch);
//                 } else if (i != 0 && i != varName.length() - 1) {
//                     print0("\\'");
//                 } else {
//                     print(ch);
//                 }
//             } else {
//                 print(ch);
//             }
//         }

//         string_ptr  collate = (string_ptr ) x.getAttribute("COLLATE");
//         if (collate != nullptr) {
//             print0(ucase ? " COLLATE " : " collate ");
//             print0(collate);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlPrepareStatement x) {
//         print0(ucase ? "PREPARE " : "prepare ");
//         x.getName().accept(this);
//         print0(ucase ? " FROM " : " from ");
//         x.getFrom().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlExecuteStatement x) {
//         print0(ucase ? "EXECUTE " : "execute ");
//         x.getStatementName().accept(this);
//         if (x.getParameters().size() > 0) {
//             print0(ucase ? " USING " : " using ");
//             printAndAccept(x.getParameters(), ", ");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlExecuteForAdsStatement x) {
//         print0(ucase ? "EXECUTE " : "execute ");
//         x.getAction().accept(this);
//         print(" ");
//         x.getRole().accept(this);
//         print(" ");
//         x.getTargetId().accept(this);
//         print(" ");
//         if (x.getStatus() != nullptr) {
//             x.getStatus().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlManageInstanceGroupStatement x) {
//         x.getOperation().accept(this);

//         print0(ucase ? " INSTANCE_GROUP " : " instance_group ");
//         printAndAccept(x.getGroupNames(), ",");

//         if (x.getReplication() != nullptr) {
//             print0(ucase ? " REPLICATION = " : " replication = ");
//             x.getReplication().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRaftMemberChangeStatement x) {
//         print0(ucase ? "SYNC RAFT_MEMBER_CHANGE " : "sync raft_member_change ");

//         if (x.isNoLeader()) {
//             print0(ucase ? "NOLEADER " : "noleader ");
//         }

//         print0(ucase ? "SHARD=" : "shard=");
//         x.getShard().accept(this);

//         print0(ucase ? " HOST=" : " host=");
//         x.getHost().accept(this);

//         print0(ucase ? " STATUS=" : " status=");
//         x.getStatus().accept(this);

//         if (x.isForce()) {
//             print0(ucase ? " FORCE" : " force");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRaftLeaderTransferStatement x) {
//         print0(ucase ? "SYNC RAFT_LEADER_TRANSFER SHARD=" : "sync raft_leader_transfer shard=");
//         x.getShard().accept(this);

//         print0(ucase ? " FROM=" : " from=");
//         x.getFrom().accept(this);

//         print0(ucase ? " TO=" : " to=");
//         x.getTo().accept(this);

//         print0(ucase ? " TIMEOUT=" : " timeout=");
//         x.getTimeout().accept(this);

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlMigrateStatement x) {
//         return BOOL::FALSE;
//     }

//     // @Override
//     void endVisit(MySqlMigrateStatement x) {
//         print0(ucase ? "MIGRATE DATABASE " : "migrate database ");
//         x.getSchema().accept(this);

//         print0(ucase ? " SHARDS=" : "shards= ");
//         x.getShardNames().accept(this);
//         print0(" ");
//         if (x.getMigrateType().getNumber().intValue() == 0) {
//             print0(ucase ? "GROUP " : "group ");
//         } else if (x.getMigrateType().getNumber().intValue() == 1) {
//             print0(ucase ? "HOST " : "host ");
//         }

//         print0(ucase ? "FROM " : "from ");
//         x.getFromInsId().accept(this);

//         if (x.getFromInsIp() != nullptr) {
//             print(":");
//             x.getFromInsIp().accept(this);
//             print(":");
//             x.getFromInsPort().accept(this);
//             print(":");
//             x.getFromInsStatus().accept(this);
//         }

//         print0(ucase ? " TO " : " to ");
//         x.getToInsId().accept(this);

//         if (x.getToInsIp() != nullptr) {
//             print(":");
//             x.getToInsIp().accept(this);
//             print(":");
//             x.getToInsPort().accept(this);
//             print(":");
//             x.getToInsStatus().accept(this);
//         }

//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowClusterNameStatement x) {
//         print0(ucase ? "SHOW CLUSTER NAME" : "show cluster name");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowJobStatusStatement x) {
//         print0(ucase ? "SHOW " : "show ");
//         if (x.isSync()) {
//             print0(ucase ? "SYNC_JOB " : "sync_job ");
//         } else {
//             print0(ucase ? "JOB " : "job ");
//         }
//         print0(ucase ? "STATUS " : "status ");

//         if (x.getWhere() != nullptr) {
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowMigrateTaskStatusStatement x) {
//         print0(ucase ? "SHOW MIGRATE TASK STATUS" : "show migrate task status");
//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(MysqlDeallocatePrepareStatement x) {
//         print0(ucase ? "DEALLOCATE PREPARE " : "deallocate prepare ");
//         x.getStatementName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlDeleteStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         if (this->isPrettyFormat() && x.hasBeforeComment()) {
//             this->printlnComments(x.getBeforeCommentsDirect());
//         }

//         print0(ucase ? "DELETE " : "delete ");

//         for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
//             SQLCommentHint hint = x.getHints().get(i);
//             hint.accept(this);
//             print(' ');
//         }

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isQuick()) {
//             print0(ucase ? "QUICK " : "quick ");
//         }

//         if (x.isIgnore()) {
//             print0(ucase ? "IGNORE " : "ignore ");
//         }

//         if (x.isForceAllPartitions()) {
//             print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
//         } else {
//             SQLName partition = x.getForcePartition();
//             if (partition != nullptr) {
//                 print0(ucase ? "FORCE PARTITION " : "force partition ");
//                 printExpr(partition, parameterized);
//                 print(' ');
//             }
//         }

//         SQLTableSource from = x.getFrom();
//         if (from == nullptr) {
//             print0(ucase ? "FROM " : "from ");
//             if (x.isFulltextDictionary()) {
//                 print0(ucase ? "FULLTEXT DICTIONARY " : "fulltext dictionary ");
//             }
//             x.getTableSource().accept(this);
//         } else {
//             x.getTableSource().accept(this);
//             println();
//             print0(ucase ? "FROM " : "from ");
//             from.accept(this);
//         }

//         SQLTableSource using = x.getUsing();
//         if (using != nullptr) {
//             println();
//             print0(ucase ? "USING " : "using ");
//             using.accept(this);
//         }

//         SQLExpr where = x.getWhere();
//         if (where != nullptr) {
//             println();
//             this->indentCount++;
//             print0(ucase ? "WHERE " : "where ");
//             printExpr(where, parameterized);
//             this->indentCount--;
//         }

//         if (x.getOrderBy() != nullptr) {
//             println();
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             println();
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlInsertStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         if (this->isPrettyFormat() && x.hasBeforeComment()) {
//             this->printlnComments(x.getBeforeCommentsDirect());
//         }

//         SQLWithSubqueryClause with = x.getWith();
//         if (with != nullptr) {
//             visit(with);
//             println();
//         }

//         print0(ucase ? "INSERT " : "insert ");

//         for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
//             SQLCommentHint hint = x.getHints().get(i);
//             hint.accept(this);
//             print(' ');
//         }

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isDelayed()) {
//             print0(ucase ? "DELAYED " : "delayed ");
//         }

//         if (x.isHighPriority()) {
//             print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
//         }

//         if (x.isIgnore()) {
//             print0(ucase ? "IGNORE " : "ignore ");
//         }

//         if (x.isRollbackOnFail()) {
//             print0(ucase ? "ROLLBACK_ON_FAIL " : "rollback_on_fail ");
//         }

//         BOOL_ptr outputIntoKeyword = BOOL::TRUE;
//         if (x.isOverwrite()) {
//             print0(ucase ? "OVERWRITE " : "overwrite ");
//         }

//         if (outputIntoKeyword) {
//             print0(ucase ? "INTO " : "into ");
//         }

//         if (x.isFulltextDictionary()) {
//             print0(ucase ? "FULLTEXT DICTIONARY " : "fulltext dictionary ");
//         }

//         SQLExprTableSource tableSource = x.getTableSource();
//         if (tableSource != nullptr) {
//             if (tableSource.getClass() == SQLExprTableSource.class) {
//                 visit(tableSource);
//             } else {
//                 tableSource.accept(this);
//             }
//         }

//         List<SQLAssignItem> partitions = x.getPartitions();
//         if (partitions != nullptr) {
//             int partitionsSize = partitions.size();
//             if (partitionsSize > 0) {
//                 print0(ucase ? " PARTITION (" : " partition (");
//                 for (int i = 0; i < partitionsSize; ++i) {
//                     if (i != 0) {
//                         print0(", ");
//                     }

//                     SQLAssignItem assign = partitions.get(i);
//                     assign.getTarget().accept(this);

//                     if (assign.getValue() != nullptr) {
//                         print('=');
//                         assign.getValue().accept(this);
//                     }
//                 }
//                 print(')');
//             }

//             if (x.isIfNotExists()) {
//                 print0(ucase ? " IF NOT EXISTS " : "if not exists ");
//             }
//         }

//         string_ptr  columnsString = x.getColumnsString();
//         if (columnsString != nullptr) {
//             if (!isEnabled(VisitorFeature.OutputSkipInsertColumnsString)) {
//                 print0(columnsString);
//             }
//         } else {
//             List<SQLExpr> columns = x.getColumns();
//             if (columns.size() > 0) {
//                 this->indentCount++;
//                 print0(" (");
//                 for (int i = 0, size = columns.size(); i < size; ++i) {
//                     if (i != 0) {
//                         if (i % 5 == 0) {
//                             println();
//                         }
//                         print0(", ");
//                     }

//                     SQLExpr column = columns.get(i);
//                     if (column instanceof SQLIdentifierExpr) {
//                         printName0(((SQLIdentifierExpr) column).getName());
//                     } else {
//                         printExpr(column, parameterized);
//                     }
//                 }
//                 print(')');
//                 this->indentCount--;
//             }
//         }

//         List<SQLInsertStatement.ValuesClause> valuesList = x.getValuesList();
//         if (!valuesList.isEmpty()) {
//             println();
//             printValuesList(valuesList);
//         }

//         if (x.getQuery() != nullptr) {
//             println();
//             x.getQuery().accept(this);
//         }

//         List<SQLExpr> duplicateKeyUpdate = x.getDuplicateKeyUpdate();
//         if (!duplicateKeyUpdate.isEmpty()) {
//             println();
//             print0(ucase ? "ON DUPLICATE KEY UPDATE " : "on duplicate key update ");
//             for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) {
//                 if (i != 0) {
//                     if (i % 5 == 0) {
//                         println();
//                     }
//                     print0(", ");
//                 }
//                 duplicateKeyUpdate.get(i).accept(this);
//             }
//         }

//         return BOOL::FALSE;
//     }

//     protected void printValuesList(List<SQLInsertStatement.ValuesClause> valuesList) {
//         if (this->parameterized
//                 && valuesList.size() > 1
//                 && !this->parameterizedQuesUnMergeValuesList) {
//             print0(ucase ? "VALUES " : "values ");
//             this->indentCount++;

//             BOOL_ptr allConst = BOOL::TRUE;
//             if (valuesList.size() > 1) {
//                 for (int index = 0; index < valuesList.size(); index++) {
//                     List<SQLExpr> values = valuesList.get(index).getValues();
//                     for (int i = 0; i < values.size(); i++) {
//                         SQLExpr value = values.get(i);
//                         if (value instanceof SQLLiteralExpr || value instanceof SQLVariantRefExpr) {
//                             continue;
//                         } else if (value instanceof SQLMethodInvokeExpr && ((SQLMethodInvokeExpr) value).getArguments().isEmpty()) {
//                             continue;
//                         }
//                         allConst = BOOL::FALSE;
//                         break;
//                     }
//                     if (!allConst) {
//                         break;
//                     }
//                 }
//             }

//             if (!allConst) {
//                 for (int index = 0; index < valuesList.size(); index++) {
//                     if (index != 0) {
//                         print(',');
//                         println();
//                     }
//                     visit(valuesList.get(index), this->parameters);
//                 }
//             } else if (valuesList.size() > 1 && this->parameters != nullptr) {
//                 SQLInsertStatement.ValuesClause first = valuesList.get(0);

//                 List<Object> valuesParameters = new ArrayList<Object>(first.getValues().size());
//                 visit(first, valuesParameters);
//                 this->parameters.add(valuesParameters);

//                 for (int index = 1; index < valuesList.size(); index++) {
//                     List<SQLExpr> values = valuesList.get(index).getValues();
//                     valuesParameters = new ArrayList<Object>(values.size());

//                     for (int i = 0, size = values.size(); i < size; ++i) {
//                         SQLExpr expr = values.get(i);
//                         if (expr instanceof SQLIntegerExpr
//                                 || expr instanceof SQLBooleanExpr
//                                 || expr instanceof SQLNumberExpr
//                                 || expr instanceof SQLCharExpr
//                                 || expr instanceof SQLNCharExpr
//                                 || expr instanceof SQLTimestampExpr
//                                 || expr instanceof SQLDateExpr
//                                 || expr instanceof SQLTimeExpr) {
//                             incrementReplaceCunt();
//                             ExportParameterVisitorUtils.exportParameter(valuesParameters, expr);
//                         } else if (expr instanceof SQLNullExpr) {
//                             incrementReplaceCunt();
//                             valuesParameters.add(nullptr);
//                         } else {
//                             // skip
//                         }
//                     }

//                     this->parameters.add(valuesParameters);
//                 }

//                 this->incrementReplaceCunt();
//             } else {
//                 if (valuesList.size() > 1) {
//                     this->incrementReplaceCunt();
//                 }
//                 visit(valuesList.get(0), this->parameters);
//             }

//             this->indentCount--;
//             return;
//         }

//         print0(ucase ? "VALUES " : "values ");
//         if (valuesList.size() > 1) {
//             this->indentCount++;
//         }
//         for (int i = 0, size = valuesList.size(); i < size; ++i) {
//             if (i != 0) {
//                 print(',');
//                 println();
//             }

//             SQLInsertStatement.ValuesClause item = valuesList.get(i);
//             visit(item, parameters);
//         }
//         if (valuesList.size() > 1) {
//             this->indentCount--;
//         }
//     }

//     // @Override
//     BOOL_ptr visit(MySqlLoadDataInFileStatement x) {
//         print0(ucase ? "LOAD DATA " : "load data ");

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isConcurrent()) {
//             print0(ucase ? "CONCURRENT " : "concurrent ");
//         }

//         if (x.isLocal()) {
//             print0(ucase ? "LOCAL " : "local ");
//         }

//         print0(ucase ? "INFILE " : "infile ");

//         x.getFileName().accept(this);

//         if (x.isReplicate()) {
//             print0(ucase ? " REPLACE " : " replace ");
//         }

//         if (x.isIgnore()) {
//             print0(ucase ? " IGNORE " : " ignore ");
//         }

//         print0(ucase ? " INTO TABLE " : " into table ");
//         x.getTableName().accept(this);

//         if (x.getColumnsTerminatedBy() != nullptr || x.getColumnsEnclosedBy() != nullptr || x.getColumnsEscaped() != nullptr) {
//             print0(ucase ? " COLUMNS" : " columns");
//             if (x.getColumnsTerminatedBy() != nullptr) {
//                 print0(ucase ? " TERMINATED BY " : " terminated by ");
//                 x.getColumnsTerminatedBy().accept(this);
//             }

//             if (x.getColumnsEnclosedBy() != nullptr) {
//                 if (x.isColumnsEnclosedOptionally()) {
//                     print0(ucase ? " OPTIONALLY" : " optionally");
//                 }
//                 print0(ucase ? " ENCLOSED BY " : " enclosed by ");
//                 x.getColumnsEnclosedBy().accept(this);
//             }

//             if (x.getColumnsEscaped() != nullptr) {
//                 print0(ucase ? " ESCAPED BY " : " escaped by ");
//                 x.getColumnsEscaped().accept(this);
//             }
//         }

//         if (x.getLinesStartingBy() != nullptr || x.getLinesTerminatedBy() != nullptr) {
//             print0(ucase ? " LINES" : " lines");
//             if (x.getLinesStartingBy() != nullptr) {
//                 print0(ucase ? " STARTING BY " : " starting by ");
//                 x.getLinesStartingBy().accept(this);
//             }

//             if (x.getLinesTerminatedBy() != nullptr) {
//                 print0(ucase ? " TERMINATED BY " : " terminated by ");
//                 x.getLinesTerminatedBy().accept(this);
//             }
//         }

//         if (x.getIgnoreLinesNumber() != nullptr) {
//             print0(ucase ? " IGNORE " : " ignore ");
//             x.getIgnoreLinesNumber().accept(this);
//             print0(ucase ? " LINES" : " lines");
//         }

//         if (!x.getColumns().isEmpty()) {
//             print0(" (");
//             printAndAccept(x.getColumns(), ", ");
//             print(')');
//         }

//         if (!x.getSetList().isEmpty()) {
//             print0(ucase ? " SET " : " set ");
//             printAndAccept(x.getSetList(), ", ");
//         }

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLReplaceStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         print0(ucase ? "REPLACE " : "replace ");

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isDelayed()) {
//             print0(ucase ? "DELAYED " : "delayed ");
//         }

//         if (x.getHints() != nullptr && x.getHints().size() > 0) {
//             printAndAccept(x.getHints(), " ");
//             print0(" ");
//         }

//         print0(ucase ? "INTO " : "into ");

//         printTableSourceExpr(x.getTableName());

//         List<SQLExpr> columns = x.getColumns();
//         if (columns.size() > 0) {
//             print0(" (");
//             for (int i = 0, size = columns.size(); i < size; ++i) {
//                 if (i != 0) {
//                     print0(", ");
//                 }

//                 SQLExpr columnn = columns.get(i);
//                 printExpr(columnn, parameterized);
//             }
//             print(')');
//         }

//         List<SQLAssignItem> partitions = x.getPartitions();
//         if (partitions != nullptr) {
//             int partitionsSize = partitions.size();
//             if (partitionsSize > 0) {
//                 print0(ucase ? " PARTITION (" : " partition (");
//                 for (int i = 0; i < partitionsSize; ++i) {
//                     if (i != 0) {
//                         print0(", ");
//                     }

//                     SQLAssignItem assign = partitions.get(i);
//                     assign.getTarget().accept(this);

//                     if (assign.getValue() != nullptr) {
//                         print('=');
//                         assign.getValue().accept(this);
//                     }
//                 }
//                 print(')');
//             }
//         }

//         List<SQLInsertStatement.ValuesClause> valuesClauseList = x.getValuesList();
//         if (!valuesClauseList.isEmpty()) {
//             println();
//             print0(ucase ? "VALUES " : "values ");
//             int size = valuesClauseList.size();
//             if (size == 0) {
//                 print0("()");
//             } else {
//                 for (int i = 0; i < size; ++i) {
//                     if (i != 0) {
//                         print0(", ");
//                     }
//                     visit(valuesClauseList.get(i));
//                 }
//             }
//         }

//         SQLQueryExpr query = x.getQuery();
//         if (query != nullptr) {
//             visit(query);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLStartTransactionStatement x) {
//         print0(ucase ? "START TRANSACTION" : "start transaction");
//         if (x.isConsistentSnapshot()) {
//             print0(ucase ? " WITH CONSISTENT SNAPSHOT" : " with consistent snapshot");
//         }

//         if (x.getHints() != nullptr && x.getHints().size() > 0) {
//             print(' ');
//             printAndAccept(x.getHints(), " ");
//         }

//         if (x.isBegin()) {
//             print0(ucase ? " BEGIN" : " begin");
//         }

//         if (x.isWork()) {
//             print0(ucase ? " WORK" : " work");
//         }

//         SQLStartTransactionStatement.IsolationLevel isolationLevel = x.getIsolationLevel();
//         if (isolationLevel != nullptr) {
//             print0(" ISOLATION LEVEL ");
//             print(isolationLevel.getText());
//         }

//         if (x.isReadOnly()) {
//             print0(ucase ? " READ ONLY" : " read only");
//         }

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLRollbackStatement x) {
//         print0(ucase ? "ROLLBACK" : "rollback");

//         if (x.getChain() != nullptr) {
//             if (x.getChain().booleanValue()) {
//                 print0(ucase ? " AND CHAIN" : " and chain");
//             } else {
//                 print0(ucase ? " AND NO CHAIN" : " and no chain");
//             }
//         }

//         if (x.getRelease() != nullptr) {
//             if (x.getRelease().booleanValue()) {
//                 print0(ucase ? " AND RELEASE" : " and release");
//             } else {
//                 print0(ucase ? " AND NO RELEASE" : " and no release");
//             }
//         }

//         if (x.getTo() != nullptr) {
//             print0(ucase ? " TO " : " to ");
//             x.getTo().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLShowTablesStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         if (x.isFull()) {
//             print0(ucase ? "SHOW FULL TABLES" : "show full tables");
//         } else {
//             print0(ucase ? "SHOW TABLES" : "show tables");
//         }

//         if (x.getDatabase() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getDatabase().accept(this);
//         }

//         SQLExpr like = x.getLike();
//         if (like != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             printExpr(like);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowHMSMetaStatement x) {
//         print0(ucase ? "SHOW HMSMETA " : "show hmsmeta ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowDatabaseStatusStatement x) {
//         if (x.isFull()) {
//             print0(ucase ? "SHOW FULL DATABASE STATUS" : "show full database status");
//         } else {
//             print0(ucase ? "SHOW DATABASE STATUS" : "show database status");
//         }

//         if (x.getName() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getName().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowWarningsStatement x) {
//         if (x.isCount()) {
//             print0(ucase ? "SHOW COUNT(*) WARNINGS" : "show count(*) warnings");
//         } else {
//             print0(ucase ? "SHOW WARNINGS" : "show warnings");
//             if (x.getLimit() != nullptr) {
//                 print(' ');
//                 x.getLimit().accept(this);
//             }
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowStatusStatement x) {
//         print0(ucase ? "SHOW " : "show ");

//         if (x.isGlobal()) {
//             print0(ucase ? "GLOBAL " : "global ");
//         }

//         if (x.isSession()) {
//             print0(ucase ? "SESSION " : "session ");
//         }

//         print0(ucase ? "STATUS" : "status");

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlLoadXmlStatement x) {
//         print0(ucase ? "LOAD XML " : "load xml ");

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isConcurrent()) {
//             print0(ucase ? "CONCURRENT " : "concurrent ");
//         }

//         if (x.isLocal()) {
//             print0(ucase ? "LOCAL " : "local ");
//         }

//         print0(ucase ? "INFILE " : "infile ");

//         x.getFileName().accept(this);

//         if (x.isReplicate()) {
//             print0(ucase ? " REPLACE " : " replace ");
//         }

//         if (x.isIgnore()) {
//             print0(ucase ? " IGNORE " : " ignore ");
//         }

//         print0(ucase ? " INTO TABLE " : " into table ");
//         x.getTableName().accept(this);

//         if (x.getCharset() != nullptr) {
//             print0(ucase ? " CHARSET " : " charset ");
//             print0(x.getCharset());
//         }

//         if (x.getRowsIdentifiedBy() != nullptr) {
//             print0(ucase ? " ROWS IDENTIFIED BY " : " rows identified by ");
//             x.getRowsIdentifiedBy().accept(this);
//         }

//         if (!x.getSetList().isEmpty()) {
//             print0(ucase ? " SET " : " set ");
//             printAndAccept(x.getSetList(), ", ");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(CobarShowStatus x) {
//         print0(ucase ? "SHOW COBAR_STATUS" : "show cobar_status");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsShowDDLJobs x) {
//         print0(ucase ? "SHOW " : "show ");
//         if (x.isFull()) {
//             print0(ucase ? "FULL " : "full ");
//         }
//         print0(ucase ? "DDL" : "ddl");
//         BOOL_ptr first = BOOL::TRUE;
//         for (Long id : x.getJobIds()) {
//             if (first) {
//                 first = BOOL::FALSE;
//                 print0(" ");
//             } else {
//                 print0(", ");
//             }
//             print(id);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsCancelDDLJob x) {
//         print0(ucase ? "CANCEL DDL" : "cancel ddl");
//         BOOL_ptr first = BOOL::TRUE;
//         for (Long id : x.getJobIds()) {
//             if (first) {
//                 first = BOOL::FALSE;
//                 print0(" ");
//             } else {
//                 print0(", ");
//             }
//             print(id);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsRecoverDDLJob x) {
//         print0(ucase ? "RECOVER DDL" : "recover ddl");
//         if (x.isAllJobs()) {
//             print0(ucase ? " ALL" : " all");
//         } else {
//             BOOL_ptr first = BOOL::TRUE;
//             for (Long id : x.getJobIds()) {
//                 if (first) {
//                     first = BOOL::FALSE;
//                     print0(" ");
//                 } else {
//                     print0(", ");
//                 }
//                 print(id);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsRollbackDDLJob x) {
//         print0(ucase ? "ROLLBACK DDL" : "rollback ddl");
//         BOOL_ptr first = BOOL::TRUE;
//         for (Long id : x.getJobIds()) {
//             if (first) {
//                 first = BOOL::FALSE;
//                 print0(" ");
//             } else {
//                 print0(", ");
//             }
//             print(id);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsRemoveDDLJob x) {
//         print0(ucase ? "REMOVE DDL" : "remove ddl");
//         if (x.isAllCompleted()) {
//             print0(ucase ? " ALL COMPLETED" : " all completed");
//         } else if (x.isAllPending()) {
//             print(ucase ? " ALL PENDING" : " all pending");
//         } else {
//             BOOL_ptr first = BOOL::TRUE;
//             for (Long id : x.getJobIds()) {
//                 if (first) {
//                     first = BOOL::FALSE;
//                     print0(" ");
//                 } else {
//                     print0(", ");
//                 }
//                 print(id);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsInspectDDLJobCache x) {
//         print0(ucase ? "INSPECT DDL CACHE" : "inspect ddl cache");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsClearDDLJobCache x) {
//         print0(ucase ? "CLEAR DDL CACHE" : "clear ddl cache");
//         if (x.isAllJobs()) {
//             print0(ucase ? " ALL" : " all");
//         } else {
//             BOOL_ptr first = BOOL::TRUE;
//             for (Long id : x.getJobIds()) {
//                 if (first) {
//                     first = BOOL::FALSE;
//                     print0(" ");
//                 } else {
//                     print0(", ");
//                 }
//                 print(id);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsChangeDDLJob x) {
//         print0(ucase ? "CHANGE DDL " : "change ddl ");
//         print(x.getJobId());
//         if (x.isSkip()) {
//             print0(ucase ? " SKIP" : " skip");
//         } else if (x.isAdd()) {
//             print0(ucase ? " ADD" : " add");
//         }

//         BOOL_ptr first = BOOL::TRUE;
//         for (string_ptr  name : x.getGroupAndTableNameList()) {
//             if (first) {
//                 first = BOOL::FALSE;
//                 print0(" ");
//             } else {
//                 print0(", ");
//             }
//             print(name);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsBaselineStatement x) {
//         print0(ucase ? "BASELINE " : "baseline ");
//         print0(ucase ? x.getOperation().toUpperCase() : x.getOperation().toLowerCase());

//         BOOL_ptr isFirst = BOOL::TRUE;
//         for (Long id : x.getBaselineIds()) {
//             if (isFirst) {
//                 print0(" ");
//                 isFirst = BOOL::FALSE;
//             } else {
//                 print0(", ");
//             }
//             print(id);
//         }

//         SQLSelect select = x.getSelect();
//         if (x.getSelect() != nullptr) {
//             print(ucase ? " SQL" : " sql");
//             println();
//             List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//             if (headHints != nullptr) {
//                 for (SQLCommentHint hint : headHints) {
//                     visit((SQLCommentHint) hint);
//                     println();
//                 }
//             }

//             this->visit(select);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsShowGlobalIndex x) {
//         print0(ucase ? "SHOW GLOBAL INDEX" : "show global index");
//         if (x.getTableName() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             printExpr(x.getTableName(), parameterized);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(DrdsShowMetadataLock x) {
//         print0(ucase ? "SHOW METADATA LOCK" : "show metadata lock");
//         if (x.getSchemaName() != nullptr) {
//             print0(" ");
//             printExpr(x.getSchemaName(), parameterized);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlBinlogStatement x) {
//         print0(ucase ? "BINLOG " : "binlog ");
//         x.getExpr().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlResetStatement x) {
//         print0(ucase ? "RESET " : "reset ");
//         for (int i = 0; i < x.getOptions().size(); ++i) {
//             if (i != 0) {
//                 print0(", ");
//             }
//             print0(x.getOptions().get(i));
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateUserStatement x) {
//         print0(ucase ? "CREATE USER " : "create user ");

//         if (x.isIfNotExists()) {
//             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
//         }

//         printAndAccept(x.getUsers(), ", ");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(UserSpecification x) {
//         x.getUser().accept(this);

//         if (x.getAuthPlugin() != nullptr) {
//             print0(ucase ? " IDENTIFIED WITH " : " identified with ");
//             x.getAuthPlugin().accept(this);
//             if (x.getPassword() != nullptr) {
//                 if (x.isPluginAs()) {
//                     print0(ucase ? " AS " : " as ");
//                 } else {
//                     print0(ucase ? " BY " : " by ");
//                 }
//                 x.getPassword().accept(this);
//             }
//         } else if (x.getPassword() != nullptr) {
//             print0(ucase ? " IDENTIFIED BY " : " identified by ");
//             if (x.isPasswordHash()) {
//                 print0(ucase ? "PASSWORD " : "password ");
//             }
//             x.getPassword().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlPartitionByKey x) {
//         if (x.isLinear()) {
//             print0(ucase ? "LINEAR KEY (" : "linear key (");
//         } else {
//             print0(ucase ? "KEY (" : "key (");
//         }
//         printAndAccept(x.getColumns(), ", ");
//         print(')');

//         printPartitionsCountAndSubPartitions(x);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPlanCacheStatusStatement x) {
//         print0(ucase ? "SHOW PLANCACHE STATUS" : "show plancache status");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlClearPlanCacheStatement x) {
//         print0(ucase ? "CLEAR PLANCACHE" : "clear plancache");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlDisabledPlanCacheStatement x) {
//         print0(ucase ? "DISABLED PLANCACHE" : "disabled plancache");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlExplainPlanCacheStatement x) {
//         print0(ucase ? "EXPLAIN PLANCACHE" : "explain plancache");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUpdatePlanCacheStatement x) {
//         print0(ucase ? "UPDATE PLANCACHE " : "update plancache ");
//         x.getFormSelect().accept(this);
//         println();
//         print0(ucase ? " TO " : " to ");
//         println();
//         x.getToSelect().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlOutFileExpr x) {
//         print0(ucase ? "OUTFILE " : "outfile ");
//         x.getFile().accept(this);

//         if (x.getCharset() != nullptr) {
//             print0(ucase ? " CHARACTER SET " : " character set ");
//             print0(x.getCharset());
//         }

//         if (x.getColumnsTerminatedBy() != nullptr || x.getColumnsEnclosedBy() != nullptr || x.getColumnsEscaped() != nullptr) {
//             print0(ucase ? " COLUMNS" : " columns");
//             if (x.getColumnsTerminatedBy() != nullptr) {
//                 print0(ucase ? " TERMINATED BY " : " terminated by ");
//                 x.getColumnsTerminatedBy().accept(this);
//             }

//             if (x.getColumnsEnclosedBy() != nullptr) {
//                 if (x.isColumnsEnclosedOptionally()) {
//                     print0(ucase ? " OPTIONALLY" : " optionally");
//                 }
//                 print0(ucase ? " ENCLOSED BY " : " enclosed by ");
//                 x.getColumnsEnclosedBy().accept(this);
//             }

//             if (x.getColumnsEscaped() != nullptr) {
//                 print0(ucase ? " ESCAPED BY " : " escaped by ");
//                 x.getColumnsEscaped().accept(this);
//             }
//         }

//         if (x.getLinesStartingBy() != nullptr || x.getLinesTerminatedBy() != nullptr) {
//             print0(ucase ? " LINES" : " lines");
//             if (x.getLinesStartingBy() != nullptr) {
//                 print0(ucase ? " STARTING BY " : " starting by ");
//                 x.getLinesStartingBy().accept(this);
//             }

//             if (x.getLinesTerminatedBy() != nullptr) {
//                 print0(ucase ? " TERMINATED BY " : " terminated by ");
//                 x.getLinesTerminatedBy().accept(this);
//             }
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlExplainStatement x) {
//         List<SQLCommentHint> hints = x.getHeadHintsDirect();
//         if (nullptr != hints) {
//             for (int i = 0; i < hints.size(); i++) {
//                 if (i != 0) {
//                     print(' ');
//                 }
//                 hints.get(i).accept(this);
//             }
//             println();
//         }

//         string_ptr  name = x.isDescribe() ? "desc" : "explain";
//         print0(ucase ? name.toUpperCase() : name);

//         hints = x.getHints();
//         if (hints != nullptr) {
//             print(' ');
//             for (int i = 0; i < hints.size(); i++) {
//                 if (i != 0) {
//                     print(' ');
//                 }
//                 hints.get(i).accept(this);
//             }
//         }

//         string_ptr  type = x.getType();
//         // tbl_name [col_name | wild]
//         if (x.getTableName() != nullptr) {
//             print(' ');
//             x.getTableName().accept(this);
//             if (x.getColumnName() != nullptr) {
//                 print(' ');
//                 x.getColumnName().accept(this);
//             } else if (x.getWild() != nullptr) {
//                 print(' ');
//                 x.getWild().accept(this);
//             }
//         } else {
//             if (x.isExtended()) {
//                 print0(ucase ? " EXTENDED" : " extended");
//             }

//             if (x.isOptimizer()) {
//                 print0(ucase ? " OPTIMIZER" : " optimizer");
//             }

//             if (x.isDependency()) {
//                 print0(ucase ? " DEPENDENCY" : " dependency");
//             }

//             if (x.isAuthorization()) {
//                 print0(ucase ? " AUTHORIZATION" : " authorization");
//             }

//             // [explain_type]
//             string_ptr  format = x.getFormat();
//             if (type != nullptr || format != nullptr) {
//                 BOOL_ptr parenthesis = x.isParenthesis();
//                 if (parenthesis) {
//                     print0(" (");
//                 } else {
//                     print(' ');
//                 }

//                 if (type != nullptr) {
//                     if (parenthesis) {
//                         print0(ucase ? "TYPE " : "type ");
//                     }
//                     print0(type);
//                 }

//                 if (format != nullptr) {
//                     if (type != nullptr) {
//                         if (parenthesis) {
//                             print0(", ");
//                         } else {
//                             print(' ');
//                         }
//                     }

//                     print0(ucase ? "FORMAT " : "format ");
//                     if (!parenthesis) {
//                         print0("= ");
//                     }
//                     print0(format);
//                 }

//                 if (parenthesis) {
//                     print(')');
//                 }
//             }

//             // {explainable_stmt | FOR CONNECTION connection_id}
//             if (x.getConnectionId() != nullptr) {
//                 print0(ucase ? " FOR CONNECTION " : " for connection ");
//                 x.getConnectionId().accept(this);
//             } else {
//                 print(' ');
//                 x.getStatement().accept(this);
//             }

//             if (x.isDistributeInfo()) {
//                 print0(ucase ? " DISTRIBUTE INFO" : " distribute info");
//             }
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUpdateStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         if (x.getWith() != nullptr) {
//             x.getWith().accept(this);
//             println();
//         }

//         List<SQLExpr> returning = x.getReturning();
//         if (returning != nullptr && returning.size() > 0) {
//             print0(ucase ? "SELECT " : "select ");
//             printAndAccept(returning, ", ");
//             println();
//             print0(ucase ? "FROM " : "from ");
//         }

//         print0(ucase ? "UPDATE " : "update ");

//         if (x.isLowPriority()) {
//             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
//         }

//         if (x.isIgnore()) {
//             print0(ucase ? "IGNORE " : "ignore ");
//         }

//         if (x.getHints() != nullptr && x.getHints().size() > 0) {
//             printAndAccept(x.getHints(), " ");
//             print0(" ");
//         }

//         if (x.isCommitOnSuccess()) {
//             print0(ucase ? "COMMIT_ON_SUCCESS " : "commit_on_success ");
//         }

//         if (x.isRollBackOnFail()) {
//             print0(ucase ? "ROLLBACK_ON_FAIL " : "rollback_on_fail ");
//         }

//         if (x.isQueryOnPk()) {
//             print0(ucase ? "QUEUE_ON_PK " : "queue_on_pk ");
//         }

//         SQLExpr targetAffectRow = x.getTargetAffectRow();
//         if (targetAffectRow != nullptr) {
//             print0(ucase ? "TARGET_AFFECT_ROW " : "target_affect_row ");
//             printExpr(targetAffectRow, parameterized);
//             print(' ');
//         }

//         if (x.isForceAllPartitions()) {
//             print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
//         } else {
//             SQLName partition = x.getForcePartition();
//             if (partition != nullptr) {
//                 print0(ucase ? "FORCE PARTITION " : "force partition ");
//                 printExpr(partition, parameterized);
//                 print(' ');
//             }
//         }

//         printTableSource(x.getTableSource());

//         println();
//         print0(ucase ? "SET " : "set ");
//         List<SQLUpdateSetItem> items = x.getItems();
//         for (int i = 0, size = items.size(); i < size; ++i) {
//             if (i != 0) {
//                 print0(", ");
//             }
//             SQLUpdateSetItem item = items.get(i);
//             visit(item);
//         }

//         SQLExpr where = x.getWhere();
//         if (where != nullptr) {
//             println();
//             indentCount++;
//             print0(ucase ? "WHERE " : "where ");
//             printExpr(where, parameterized);
//             indentCount--;
//         }

//         SQLOrderBy orderBy = x.getOrderBy();
//         if (orderBy != nullptr) {
//             println();
//             visit(orderBy);
//         }

//         SQLLimit limit = x.getLimit();
//         if (limit != nullptr) {
//             println();
//             visit(limit);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlSetTransactionStatement x) {
//         print0(ucase ? "SET " : "set ");
//         if (x.getGlobal() != nullptr && x.getGlobal()) {
//             print0(ucase ? "GLOBAL " : "global ");
//         } else if (x.getSession() != nullptr && x.getSession()) {
//             print0(ucase ? "SESSION " : "session ");
//         }

//         print0(ucase ? "TRANSACTION " : "transaction ");

//         if (x.getIsolationLevel() != nullptr) {
//             print0(ucase ? "ISOLATION LEVEL " : "isolation level ");
//             print0(x.getIsolationLevel());
//         }

//         string_ptr  accessModel = x.getAccessModel();
//         if (accessModel != nullptr) {
//             print0(ucase ? "READ " : "read ");
//             print0(accessModel);
//         }

//         SQLExpr policy = x.getPolicy();
//         if (policy != nullptr) {
//             print0(ucase ? "POLICY " : "policy ");
//             policy.accept(this);
//         }

//         return BOOL::FALSE;
//     }

// //
// //    // @Override
// //    BOOL_ptr visit(MySqlSetNamesStatement x) {
// //        print0(ucase ? "SET NAMES " : "set names ");
// //        if (x.isDefault()) {
// //            print0(ucase ? "DEFAULT" : "default");
// //        } else {
// //            print0(x.getCharSet());
// //            if (x.getCollate() != nullptr) {
// //                print0(ucase ? " COLLATE " : " collate ");
// //                print0(x.getCollate());
// //            }
// //        }
// //        return BOOL::FALSE;
// //    }

// //    BOOL_ptr visit(MySqlSetCharSetStatement x) {
// //        print0(ucase ? "SET CHARACTER SET " : "set character set ");
// //        if (x.isDefault()) {
// //            print0(ucase ? "DEFAULT" : "default");
// //        } else {
// //            print0(x.getCharSet());
// //            if (x.getCollate() != nullptr) {
// //                print0(ucase ? " COLLATE " : " collate ");
// //                print0(x.getCollate());
// //            }
// //        }
// //        return BOOL::FALSE;
// //    }

//     // @Override
//     BOOL_ptr visit(MySqlShowAuthorsStatement x) {
//         print0(ucase ? "SHOW AUTHORS" : "show authors");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowBinaryLogsStatement x) {
//         print0(ucase ? "SHOW BINARY LOGS" : "show binary logs");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowMasterLogsStatement x) {
//         print0(ucase ? "SHOW MASTER LOGS" : "show master logs");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCollationStatement x) {
//         print0(ucase ? "SHOW COLLATION" : "show collation");
//         if (x.getPattern() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getPattern().accept(this);
//         }
//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowBinLogEventsStatement x) {
//         print0(ucase ? "SHOW BINLOG EVENTS" : "show binlog events");
//         if (x.getIn() != nullptr) {
//             print0(ucase ? " IN " : " in ");
//             x.getIn().accept(this);
//         }
//         if (x.getFrom() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getFrom().accept(this);
//         }
//         if (x.getLimit() != nullptr) {
//             print(' ');
//             x.getLimit().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCharacterSetStatement x) {
//         print0(ucase ? "SHOW CHARACTER SET" : "show character set");
//         if (x.getPattern() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getPattern().accept(this);
//         }
//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowContributorsStatement x) {
//         print0(ucase ? "SHOW CONTRIBUTORS" : "show contributors");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCreateDatabaseStatement x) {
//         print0(ucase ? "SHOW CREATE DATABASE " : "show create database ");
//         if (x.isIfNotExists()) {
//             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
//         }
//         x.getDatabase().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCreateEventStatement x) {
//         print0(ucase ? "SHOW CREATE EVENT " : "show create event ");
//         x.getEventName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCreateFunctionStatement x) {
//         print0(ucase ? "SHOW CREATE FUNCTION " : "show create function ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCreateProcedureStatement x) {
//         print0(ucase ? "SHOW CREATE PROCEDURE " : "show create procedure ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowCreateTriggerStatement x) {
//         print0(ucase ? "SHOW CREATE TRIGGER " : "show create trigger ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowEngineStatement x) {
//         print0(ucase ? "SHOW ENGINE " : "show engine ");
//         x.getName().accept(this);
//         print(' ');
//         print0(x.getOption().name());
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowEventsStatement x) {
//         print0(ucase ? "SHOW EVENTS" : "show events");
//         if (x.getSchema() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getSchema().accept(this);
//         }

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowFunctionCodeStatement x) {
//         print0(ucase ? "SHOW FUNCTION CODE " : "show function code ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowFunctionStatusStatement x) {
//         print0(ucase ? "SHOW FUNCTION STATUS" : "show function status");
//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowEnginesStatement x) {
//         if (x.isStorage()) {
//             print0(ucase ? "SHOW STORAGE ENGINES" : "show storage engines");
//         } else {
//             print0(ucase ? "SHOW ENGINES" : "show engines");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowErrorsStatement x) {
//         if (x.isCount()) {
//             print0(ucase ? "SHOW COUNT(*) ERRORS" : "show count(*) errors");
//         } else {
//             print0(ucase ? "SHOW ERRORS" : "show errors");
//             if (x.getLimit() != nullptr) {
//                 print(' ');
//                 x.getLimit().accept(this);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowGrantsStatement x) {
//         print0(ucase ? "SHOW GRANTS" : "show grants");
//         SQLExpr user = x.getUser();
//         if (user != nullptr) {
//             print0(ucase ? " FOR " : " for ");
//             user.accept(this);
//         }

//         SQLExpr on = x.getOn();
//         if (on != nullptr) {
//             print0(ucase ? " ON " : " on ");
//             on.accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUserName x) {
//         string_ptr  userName = x.getUserName();

//         if (userName.length() > 0 && userName.charAt(0) == '\'') {
//             print0(userName);
//         } else {
//             print('\'');
//             print0(userName);
//             print('\'');
//         }

//         string_ptr  host = x.getHost();
//         if (host != nullptr) {
//             print('@');

//             if (host.length() > 0 && host.charAt(0) == '\'') {
//                 print0(host);
//             } else {
//                 print('\'');
//                 print0(host);
//                 print('\'');
//             }
//         }

//         string_ptr  identifiedBy = x.getIdentifiedBy();
//         if (identifiedBy != nullptr) {
//             print0(ucase ? " IDENTIFIED BY '" : " identified by '");
//             print0(identifiedBy);
//             print('\'');
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowMasterStatusStatement x) {
//         print0(ucase ? "SHOW MASTER STATUS" : "show master status");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowOpenTablesStatement x) {
//         print0(ucase ? "SHOW OPEN TABLES" : "show open tables");

//         if (x.getDatabase() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getDatabase().accept(this);
//         }

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPluginsStatement x) {
//         print0(ucase ? "SHOW PLUGINS" : "show plugins");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPartitionsStatement x) {
//         print0(ucase ? "SHOW DBPARTITIONS " : "show dbpartitions ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLShowPartitionsStmt x) {
//         print0(ucase ? "SHOW PARTITIONS FROM " : "show partitions from ");
//         x.getTableSource().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPrivilegesStatement x) {
//         print0(ucase ? "SHOW PRIVILEGES" : "show privileges");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowProcedureCodeStatement x) {
//         print0(ucase ? "SHOW PROCEDURE CODE " : "show procedure code ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowProcedureStatusStatement x) {
//         print0(ucase ? "SHOW PROCEDURE STATUS" : "show procedure status");
//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowProcessListStatement x) {
//         return visit((SQLShowProcessListStatement) x);
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowProfileStatement x) {
//         print0(ucase ? "SHOW PROFILE" : "show profile");
//         for (int i = 0; i < x.getTypes().size(); ++i) {
//             if (i == 0) {
//                 print(' ');
//             } else {
//                 print0(", ");
//             }
//             print0(x.getTypes().get(i).name);
//         }

//         if (x.getForQuery() != nullptr) {
//             print0(ucase ? " FOR QUERY " : " for query ");
//             x.getForQuery().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print(' ');
//             x.getLimit().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowProfilesStatement x) {
//         print0(ucase ? "SHOW PROFILES" : "show profiles");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowRelayLogEventsStatement x) {
//         print0("SHOW RELAYLOG EVENTS");

//         if (x.getLogName() != nullptr) {
//             print0(ucase ? " IN " : " in ");
//             x.getLogName().accept(this);
//         }

//         if (x.getFrom() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getFrom().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print(' ');
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowSlaveHostsStatement x) {
//         print0(ucase ? "SHOW SLAVE HOSTS" : "show slave hosts");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowSlowStatement x) {
//         print0(ucase ? "SHOW " : "show ");

//         if (x.isFull()) {
//             print0(ucase ? "FULL " : "full ");
//         }
//         if (x.isPhysical()) {
//             print0(ucase ? "PHYSICAL_SLOW" : "PHYSICAL_SLOW");
//         } else {
//             print0(ucase ? "SLOW" : "slow");
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowSequencesStatement x) {
//         print0(ucase ? "SHOW SEQUENCES" : "show sequences");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowSlaveStatusStatement x) {
//         print0(ucase ? "SHOW SLAVE STATUS" : "show slave status");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowTableStatusStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         print0(ucase ? "SHOW TABLE STATUS" : "show table status");
//         if (x.getDatabase() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getDatabase().accept(this);
//             if (x.getTableGroup() != nullptr) {
//                 print0(".");
//                 x.getTableGroup().accept(this);
//             }
//         }

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlShowDbLockStatement x) {
//         print0(ucase ? "SHOW DBLOCK" : "show dblock");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlShowHtcStatement x) {
//         print0(ucase ? "SHOW HTC" : "show htc");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlShowStcStatement x) {
//         if (x.isHis()) {
//             print0(ucase ? "SHOW STC HIS" : "show stc his");
//         } else {
//             print0(ucase ? "SHOW STC" : "show stc");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowTriggersStatement x) {
//         print0(ucase ? "SHOW TRIGGERS" : "show triggers");

//         if (x.getDatabase() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getDatabase().accept(this);
//         }

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowRuleStatement x) {
//         print0(ucase ? "SHOW " : "show ");

//         if (x.isFull()) {
//             print0(ucase ? "FULL RULE" : "full rule");
//         } else {
//             print0(ucase ? "RULE" : "rule");
//         }

//         if (x.isVersion()) {
//             print0(ucase ? " VERSION" : " version");
//         }

//         if (x.getName() != nullptr) {
//             print0(ucase ? " FROM " : " from ");
//             x.getName().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowRuleStatusStatement x) {
//         print0(ucase ? "SHOW RULE" : "show rule");

//         if (x.isFull()) {
//             print0(ucase ? " FULL" : " full");
//         } else if (x.isVersion()) {
//             print0(ucase ? " VERSION" : " version");
//         }

//         print0(ucase ? " STATUS" : " status");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPhysicalProcesslistStatement x) {
//         print0(ucase ? "SHOW" : "show");

//         if (x.isFull()) {
//             print0(ucase ? " FULL" : " full");
//         }

//         print0(ucase ? " PHYSICAL_PROCESSLIST" : " physical_processlist");

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRenameSequenceStatement x) {
//         print0(ucase ? "RENAME SEQUENCE " : "rename sequence ");
//         x.getName().accept(this);
//         print0(ucase ? " TO " : " to ");
//         x.getTo().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCheckTableStatement x) {
//         print0(ucase ? "CHECK TABLE " : "check table ");
//         printAndAccept(x.getTables(), "，");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlCreateFullTextCharFilterStatement x) {
//         print0(ucase ? "CREATE FULLTEXT CHARFILTER " : "create fulltext charfilter ");
//         x.getName().accept(this);
//         println("(");
//         print0("\"type\" = " + x.getTypeName());
//         println(",");
//         printAndAccept(x.getOptions(), ",");

//         println();
//         print0(")");

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlShowFullTextStatement x) {
//         print0(ucase ? "SHOW FULLTEXT " : "show fulltext ");
//         if (x.getType() == FullTextType.DICTIONARY) {
//             print0(ucase ? "DICTIONARIES" : "dictionaries");
//         } else {
//             print0(ucase ? x.getType().toString().toUpperCase() + "S" : x.getType().toString().toLowerCase() + "s");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlShowCreateFullTextStatement x) {
//         print0(ucase ? "SHOW CREATE FULLTEXT " : "show create fulltext ");
//         print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());
//         print0(" ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlAlterFullTextStatement x) {
//         print0(ucase ? "ALTER FULLTEXT " : "alter fulltext ");
//         print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());
//         print0(" ");
//         x.getName().accept(this);
//         print0(ucase ? " SET " : " set ");
//         x.getItem().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableDropClusteringKey x) {
//         print0(ucase ? "DROP CLUSTERED KEY " : "drop clustered key ");
//         x.getKeyName().accept(this);

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlDropFullTextStatement x) {
//         print0(ucase ? "DROP FULLTEXT " : "drop fulltext ");
//         print0(ucase ? x.getType().toString().toUpperCase() : x.getType().toString().toLowerCase());
//         print0(" ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlCreateFullTextTokenizerStatement x) {
//         print0(ucase ? "CREATE FULLTEXT TOKENIZER " : "create fulltext tokenizer ");
//         x.getName().accept(this);
//         println("(");
//         print0("\"type\" = " + x.getTypeName());
//         if (x.getUserDefinedDict() != nullptr) {
//             println(",");
//             print("\"user_defined_dict\" = " + x.getUserDefinedDict());
//         }
//         if (!x.getOptions().isEmpty()) {
//             println(",");
//             printAndAccept(x.getOptions(), ",");
//         }
//         println();
//         print0(")");

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlCreateFullTextTokenFilterStatement x) {
//         print0(ucase ? "CREATE FULLTEXT TOKENFILTER " : "create fulltext tokenfilter ");
//         x.getName().accept(this);
//         println("(");
//         println("\"type\" = " + x.getTypeName() + ",");
//         printAndAccept(x.getOptions(), ",");

//         println();
//         print0(")");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlCreateFullTextAnalyzerStatement x) {
//         print0(ucase ? "CREATE FULLTEXT ANALYZER " : "create fulltext analyzer ");
//         x.getName().accept(this);
//         println("(");
//         print0(ucase ? "\"TOKENIZER\" = " : "\"tokenizer\" = ");
//         print0(x.getTokenizer());
//         println(",");

//         if (!x.getCharfilters().isEmpty()) {
//             print0(ucase ? "\"CHARFILTER\" = [" : "\"charfilter\" = [");
//             for (int i = 0; i < x.getCharfilters().size(); i++) {
//                 if (i != 0) {
//                     print0(", ");
//                 }

//                 print0("\"" + x.getCharfilters().get(i) + "\"");
//             }
//             println("],");
//         }
//         if (!x.getTokenizers().isEmpty()) {
//             print0(ucase ? "\"TOKENFILTER\" = [" : "\"tokenfilter\" = [");
//             for (int i = 0; i < x.getTokenizers().size(); i++) {
//                 if (i != 0) {
//                     print0(", ");
//                 }

//                 print0("\"" + x.getTokenizers().get(i) + "\"");
//             }
//             print0("]");
//         }
//         println();
//         print0(")");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlCreateFullTextDictionaryStatement x) {
//         print0(ucase ? "CREATE FULLTEXT DICTIONARY " : "create fulltext dictionary ");
//         x.getName().accept(this);
//         println("(");
//         x.getColumn().accept(this);
//         println();
//         print0(") ");

//         if (x.getComment() != nullptr) {
//             print0(ucase ? "COMMENT " : "comment ");
//             print0(x.getComment());
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableAlterFullTextIndex x) {
//         print0(ucase ? " ALTER INDEX " : " alter index ");
//         x.getIndexName().accept(this);
//         print0(ucase ? " FULLTEXT " : " fulltext ");
//         if (x.getAnalyzerType() != nullptr) {
//             string_ptr  analyzerType = x.getAnalyzerType().toString();
//             print0(ucase ? analyzerType.toUpperCase() : analyzerType.toLowerCase());
//         }
//         print0(ucase ? " ANALYZER = " : " analyzer = ");
//         x.getAnalyzerName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlExtPartition x) {
//         print0(ucase ? "EXTPARTITION (" : "extpartition (");
//         incrementIndent();
//         println();
//         for (int i = 0; i < x.getItems().size(); i++) {
//             if (i != 0) {
//                 println(", ");
//             }
//             MySqlExtPartition.Item item = x.getItems().get(i);
//             item.accept(this);
//         }
//         decrementIndent();
//         println();
//         print(')');
//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(MySqlExtPartition.Item x) {
//         SQLName dbPartition = x.getDbPartition();
//         if (dbPartition != nullptr) {
//             print0(ucase ? "DBPARTITION " : "dbpartition ");
//             dbPartition.accept(this);

//             SQLExpr dbPartitionBy = x.getDbPartitionBy();
//             if (dbPartitionBy != nullptr) {
//                 print0(ucase ? " BY " : " by ");
//             }
//             dbPartitionBy.accept(this);
//         }

//         SQLName tbPartition = x.getTbPartition();
//         if (tbPartition != nullptr) {
//             if (dbPartition != nullptr) {
//                 print(' ');
//             }

//             print0(ucase ? "TBPARTITION " : "tbpartition ");
//             tbPartition.accept(this);

//             SQLExpr tbPartitionBy = x.getTbPartitionBy();
//             if (tbPartitionBy != nullptr) {
//                 print0(ucase ? " BY " : " by ");
//             }
//             tbPartitionBy.accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowTraceStatement x) {
//         print0(ucase ? "SHOW TRACE" : "show trace");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowBroadcastsStatement x) {
//         print0(ucase ? "SHOW BROADCASTS" : "show broadcasts");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowDatasourcesStatement x) {
//         print0(ucase ? "SHOW DATASOURCES" : "show datasources");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowNodeStatement x) {
//         print0(ucase ? "SHOW NODE" : "show node");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowHelpStatement x) {
//         print0(ucase ? "SHOW HELP" : "show help");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlFlashbackStatement x) {
//         print0(ucase ? "FLASHBACK TABLE " : "flashback table ");
//         x.getName().accept(this);
//         print0(ucase ? " TO BEFORE DROP" : " to before drop");

//         SQLName renameTo = x.getRenameTo();
//         if (renameTo != nullptr) {
//             print0(ucase ? " RENAME TO " : " rename to ");
//             renameTo.accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowConfigStatement x) {
//         print0(ucase ? "SHOW CONFIG " : "show config ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowPlanCacheStatement x) {
//         print0(ucase ? "SHOW PLANCACHE PLAN" : "show plancache plan");
//         println();
//         x.getSelect().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowDdlStatusStatement x) {
//         print0(ucase ? "SHOW DDL STATUS" : "show ddl status");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowDsStatement x) {
//         print0(ucase ? "SHOW DS" : "show ds");

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlShowTopologyStatement x) {
//         print0(ucase ? "SHOW " : "show ");

//         if (x.isFull()) {
//             print0(ucase ? "FULL " : "full ");
//         }

//         print0(ucase ? "TOPOLOGY FROM " : "topology from ");

//         print0(x.getName().getSimpleName());

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         if (x.getOrderBy() != nullptr) {
//             print0(" ");
//             x.getOrderBy().accept(this);
//         }

//         if (x.getLimit() != nullptr) {
//             print0(" ");
//             x.getLimit().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLShowVariantsStatement x) {
//         print0(ucase ? "SHOW " : "show ");

//         if (x.isGlobal()) {
//             print0(ucase ? "GLOBAL " : "global ");
//         }

//         if (x.isSession()) {
//             print0(ucase ? "SESSION " : "session ");
//         }

//         print0(ucase ? "VARIABLES" : "variables");

//         if (x.getLike() != nullptr) {
//             print0(ucase ? " LIKE " : " like ");
//             x.getLike().accept(this);
//         }

//         if (x.getWhere() != nullptr) {
//             print0(ucase ? " WHERE " : " where ");
//             x.getWhere().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableStatement x) {
//         List<SQLCommentHint> headHints = x.getHeadHintsDirect();
//         if (headHints != nullptr) {
//             for (SQLCommentHint hint : headHints) {
//                 hint.accept(this);
//                 println();
//             }
//         }

//         print0(ucase ? "ALTER " : "alter ");
//         if (x.isOnline()) {
//             print0(ucase ? "ONLINE  " : "online ");
//         } else if (x.isOffline()) {
//             print0(ucase ? "OFFLINE  " : "offline ");
//         }
//         if (x.isIgnore()) {
//             print0(ucase ? "IGNORE " : "ignore ");
//         }
//         print0(ucase ? "TABLE " : "table ");

//         printTableSourceExpr(x.getName());
//         this->indentCount++;
//         for (int i = 0; i < x.getItems().size(); ++i) {
//             SQLAlterTableItem item = x.getItems().get(i);
//             if (i != 0) {
//                 print(',');
//             }
//             println();
//             item.accept(this);
//         }

//         if (x.isRemovePatiting()) {
//             println();
//             print0(ucase ? "REMOVE PARTITIONING" : "remove partitioning");
//         }

//         if (x.isUpgradePatiting()) {
//             println();
//             print0(ucase ? "UPGRADE PARTITIONING" : "upgrade partitioning");
//         }

//         if (x.getTableOptions().size() > 0) {
//             if (x.getItems().size() > 0) {
//                 print(',');
//             }
//             println();
//         }

//         this->indentCount--;

//         int i = 0;
//         for (SQLAssignItem item : x.getTableOptions()) {
//             SQLExpr key = item.getTarget();
//             if (i != 0) {
//                 print(' ');
//             }
//             print0(ucase ? key.toString().toUpperCase() : key.toString().toLowerCase());

//             if ("TABLESPACE".equals(key)) {
//                 print(' ');
//                 item.getValue().accept(this);
//                 continue;
//             } else if ("UNION".equals(key)) {
//                 print0(" = (");
//                 item.getValue().accept(this);
//                 print(')');
//                 continue;
//             }

//             print0(" = ");

//             item.getValue().accept(this);
//             i++;
//         }

//         SQLPartitionBy partitionBy = x.getPartition();
//         if (partitionBy != nullptr) {
//             println();
//             print0(ucase ? "PARTITION BY " : "partition by ");
//             partitionBy.accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableAddColumn x) {
//         print0(ucase ? "ADD COLUMN " : "add column ");

//         if (x.getColumns().size() > 1) {
//             print('(');
//         }
//         printAndAccept(x.getColumns(), ", ");
//         if (x.getFirstColumn() != nullptr) {
//             print0(ucase ? " FIRST " : " first ");
//             x.getFirstColumn().accept(this);
//         } else if (x.getAfterColumn() != nullptr) {
//             print0(ucase ? " AFTER " : " after ");
//             x.getAfterColumn().accept(this);
//         } else if (x.isFirst()) {
//             print0(ucase ? " FIRST" : " first");
//         }

//         if (x.getColumns().size() > 1) {
//             print(')');
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRenameTableStatement.Item x) {
//         x.getName().accept(this);
//         print0(ucase ? " TO " : " to ");
//         x.getTo().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRenameTableStatement x) {
//         print0(ucase ? "RENAME TABLE " : "rename table ");
//         printAndAccept(x.getItems(), ", ");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUseIndexHint x) {
//         print0(ucase ? "USE INDEX " : "use index ");
//         if (x.getOption() != nullptr) {
//             print0(ucase ? "FOR " : "for ");
//             print0(x.getOption().name);
//             print(' ');
//         }
//         print('(');
//         printAndAccept(x.getIndexList(), ", ");
//         print(')');
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlIgnoreIndexHint x) {
//         print0(ucase ? "IGNORE INDEX " : "ignore index ");
//         if (x.getOption() != nullptr) {
//             print0(ucase ? "FOR " : "for ");
//             print0(ucase ? x.getOption().name : x.getOption().nameLCase);
//             print(' ');
//         }
//         print('(');
//         printAndAccept(x.getIndexList(), ", ");
//         print(')');
//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLExprTableSource x) {
//         printTableSourceExpr(x.getExpr());

//         SQLTableSampling sampling = x.getSampling();
//         if (sampling != nullptr) {
//             print(' ');
//             sampling.accept(this);
//         }

//         string_ptr  alias = x.getAlias();
//         List<SQLName> columns = x.getColumnsDirect();
//         if (alias != nullptr) {
//             print(' ');
//             if (columns != nullptr && columns.size() > 0) {
//                 print0(ucase ? " AS " : " as ");
//             }
//             print0(alias);
//         }

//         if (columns != nullptr && columns.size() > 0) {
//             print(" (");
//             printAndAccept(columns, ", ");
//             print(')');
//         }

//         for (int i = 0; i < x.getHintsSize(); ++i) {
//             print(' ');
//             x.getHints().get(i).accept(this);
//         }

//         if (x.getPartitionSize() > 0) {
//             print0(ucase ? " PARTITION (" : " partition (");
//             printlnAndAccept(x.getPartitions(), ", ");
//             print(')');
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlLockTableStatement x) {
//         print0(ucase ? "LOCK TABLES" : "lock tables");
//         List<MySqlLockTableStatement.Item> items = x.getItems();
//         if (items.size() > 0) {
//             print(' ');
//             printAndAccept(items, ", ");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlLockTableStatement.Item x) {
//         x.getTableSource().accept(this);
//         if (x.getLockType() != nullptr) {
//             print(' ');
//             print0(x.getLockType().name);
//         }

//         if (x.getHints() != nullptr && x.getHints().size() > 0) {
//             print(' ');
//             printAndAccept(x.getHints(), " ");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUnlockTablesStatement x) {
//         print0(ucase ? "UNLOCK TABLES" : "unlock tables");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlForceIndexHint x) {
//         print0(ucase ? "FORCE INDEX " : "force index ");
//         if (x.getOption() != nullptr) {
//             print0(ucase ? "FOR " : "for ");
//             print0(x.getOption().name);
//             print(' ');
//         }
//         print('(');
//         printAndAccept(x.getIndexList(), ", ");
//         print(')');
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableChangeColumn x) {
//         print0(ucase ? "CHANGE COLUMN " : "change column ");
//         x.getColumnName().accept(this);
//         print(' ');
//         x.getNewColumnDefinition().accept(this);
//         if (x.getFirstColumn() != nullptr) {
//             print0(ucase ? " FIRST " : " first ");
//             x.getFirstColumn().accept(this);
//         } else if (x.getAfterColumn() != nullptr) {
//             print0(ucase ? " AFTER " : " after ");
//             x.getAfterColumn().accept(this);
//         } else if (x.isFirst()) {
//             print0(ucase ? " FIRST" : " first");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableModifyColumn x) {
//         print0(ucase ? "MODIFY COLUMN " : "modify column ");
//         x.getNewColumnDefinition().accept(this);
//         if (x.getFirstColumn() != nullptr) {
//             print0(ucase ? " FIRST " : " first ");
//             x.getFirstColumn().accept(this);
//         } else if (x.getAfterColumn() != nullptr) {
//             print0(ucase ? " AFTER " : " after ");
//             x.getAfterColumn().accept(this);
//         } else if (x.isFirst()) {
//             print0(ucase ? " FIRST" : " first");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableOption x) {
//         print0(x.getName());
//         print0(" = ");
//         print0(x.getValue().toString());
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterDatabaseSetOption x) {
//         print0(ucase ? "SET " : "set ");
//         printAndAccept(x.getOptions(), ", ");

//         SQLName on = x.getOn();
//         if (on != nullptr) {
//             print0(ucase ? " ON " : " on ");
//             on.accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterDatabaseKillJob x) {
//         print0(ucase ? "KILL " : "kill ");
//         x.getJobType().accept(this);
//         print0(" ");
//         x.getJobId().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlHelpStatement x) {
//         print0(ucase ? "HELP " : "help ");
//         x.getContent().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCharExpr x) {
//         if (this->parameterized) {
//             print('?');
//             incrementReplaceCunt();
//             if (this->parameters != nullptr) {
//                 ExportParameterVisitorUtils.exportParameter(this->parameters, x);
//             }
//             return BOOL::FALSE;
//         }

//         string_ptr  charset = x.getCharset();
//         string_ptr  collate = x.getCollate();
//         string_ptr  text = x.getText();

//         if (charset != nullptr) {
//             print(charset);

//             long charsetHashCode = FnvHash.hashCode64(charset);
//             if (charsetHashCode == FnvHash.Constants._UCS2 || charsetHashCode == FnvHash.Constants._UTF16) {
//                 print(" x'");
//             } else {
//                 print(" '");
//             }
//             print(text);
//             print('\'');
//         } else {
//             print('\'');
//             print(text);
//             print('\'');
//         }

//         if (collate != nullptr) {
//             print(" COLLATE ");
//             print(collate);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUnique x) {
//         visit(x.getIndexDefinition());
//         /*
//         if (x.isHasConstraint()) {
//             print0(ucase ? "CONSTRAINT " : "constraint ");
//             if (x.getName() != nullptr) {
//                 x.getName().accept(this);
//                 print(' ');
//             }
//         }

//         if (x.isGlobal()) {
//             print0(ucase ? "GLOBAL " : "global ");
//         }

//         print0(ucase ? "UNIQUE" : "unique");

//         SQLName name = x.getName();
//         if (name != nullptr) {
//             print(' ');
//             name.accept(this);
//         }

//         if (x.getIndexType() != nullptr) {
//             print0(ucase ? " USING " : " using ");
//             print0(x.getIndexType());
//         }

//         print0(" (");
//         printAndAccept(x.getColumns(), ", ");
//         print(')');

//         List<SQLName> covering = x.getCovering();
//         if (covering.size() > 0) {
//             print0(ucase ? " COVERING (" : " covering (");
//             printAndAccept(covering, ", ");
//             print(')');
//         }

//         SQLPartitionBy dbPartitionBy = x.getDbPartitionBy();
//         if (dbPartitionBy != nullptr) {
//             print0(ucase ? " DBPARTITION BY " : " dbpartition by ");
//             dbPartitionBy.accept(this);
//         }

//         SQLExpr tablePartitionBy = x.getTablePartitionBy();
//         if (tablePartitionBy != nullptr) {
//             print0(ucase ? " TBPARTITION BY " : " tbpartition by ");
//             tablePartitionBy.accept(this);
//         }

//         SQLExpr tablePartitions = x.getTablePartitions();
//         if (tablePartitions != nullptr) {
//             print0(ucase ? " TBPARTITIONS " : " tbpartitions ");
//             tablePartitions.accept(this);
//         }

//         SQLExpr keyBlockSize = x.getKeyBlockSize();
//         if (keyBlockSize != nullptr) {
//             print0(ucase ? " KEY_BLOCK_SIZE = " : " key_block_size = ");
//             keyBlockSize.accept(this);
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             comment.accept(this);
//         }
//         */

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MysqlForeignKey x) {
//         if (x.isHasConstraint()) {
//             print0(ucase ? "CONSTRAINT " : "constraint ");
//             if (x.getName() != nullptr) {
//                 x.getName().accept(this);
//                 print(' ');
//             }
//         }

//         print0(ucase ? "FOREIGN KEY" : "foreign key");

//         if (x.getIndexName() != nullptr) {
//             print(' ');
//             x.getIndexName().accept(this);
//         }

//         print0(" (");
//         printAndAccept(x.getReferencingColumns(), ", ");
//         print(')');

//         print0(ucase ? " REFERENCES " : " references ");
//         x.getReferencedTableName().accept(this);

//         print0(" (");
//         printAndAccept(x.getReferencedColumns(), ", ");
//         print(')');

//         SQLForeignKeyImpl.Match match = x.getReferenceMatch();
//         if (match != nullptr) {
//             print0(ucase ? " MATCH " : " match ");
//             print0(ucase ? match.name : match.nameLCase);
//         }

//         if (x.getOnDelete() != nullptr) {
//             print0(ucase ? " ON DELETE " : " on delete ");
//             print0(ucase ? x.getOnDelete().name : x.getOnDelete().nameLCase);
//         }

//         if (x.getOnUpdate() != nullptr) {
//             print0(ucase ? " ON UPDATE " : " on update ");
//             print0(ucase ? x.getOnUpdate().name : x.getOnUpdate().nameLCase);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableDiscardTablespace x) {
//         print0(ucase ? "DISCARD TABLESPACE" : "discard tablespace");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateExternalCatalogStatement x) {
//         print0(ucase ? "CREATE EXTERNAL CATALOG " : "create external catalog ");

//         if (x.isIfNotExists()) {
//             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
//         }

//         x.getName().accept(this);

//         print0(ucase ? " PROPERTIES (" : " properties (");

//         for (Map.Entry<SQLName, SQLName> entry : x.getProperties().entrySet()) {
//             println();
//             entry.getKey().accept(this);
//             print0("=");
//             entry.getValue().accept(this);
//         }
//         print0(")");

//         if (x.getComment() != nullptr) {
//             println();
//             print0(ucase ? "COMMENT " : "comment ");
//             x.getComment().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableImportTablespace x) {
//         print0(ucase ? "IMPORT TABLESPACE" : "import tablespace");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAssignItem x) {
//         string_ptr  tagetString = x.getTarget().toString();

//         BOOL_ptr mysqlSpecial = BOOL::FALSE;

//         if (DbType::mysql == dbType) {
//             mysqlSpecial = "NAMES".equalsIgnoreCase(tagetString)
//                     || "CHARACTER SET".equalsIgnoreCase(tagetString)
//                     || "CHARSET".equalsIgnoreCase(tagetString);
//         }

//         if (!mysqlSpecial) {
//             x.getTarget().accept(this);
//             print0(" = ");
//         } else {
//             print0(ucase ? tagetString.toUpperCase() : tagetString.toLowerCase());
//             print(' ');
//         }
//         x.getValue().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(TableSpaceOption x) {
//         x.getName().accept(this);

//         if (x.getStorage() != nullptr) {
//             print(ucase ? " STORAGE " : " storage ");
//             x.getStorage().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     protected void visitAggreateRest(SQLAggregateExpr aggregateExpr) {
//         {
//             SQLOrderBy value = aggregateExpr.getOrderBy();
//             if (value != nullptr) {
//                 print(' ');
//                 ((SQLObject) value).accept(this);
//             }
//         }
//         {
//             Object value = aggregateExpr.getAttribute("SEPARATOR");
//             if (value != nullptr) {
//                 print0(ucase ? " SEPARATOR " : " separator ");
//                 ((SQLObject) value).accept(this);
//             }
//         }
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAnalyzeStatement x) {
//         print0(ucase ? "ANALYZE " : "analyze ");
//         if (x.isNoWriteToBinlog()) {
//             print0(ucase ? "NO_WRITE_TO_BINLOG " : "no_write_to_binlog ");
//         }

//         if (x.isLocal()) {
//             print0(ucase ? "LOCAL " : "local ");
//         }

//         if (!x.getAdbColumns().isEmpty()) {
//             print0(ucase ? "COLUMN " : "column ");
//         } else if (!x.getAdbColumnsGroup().isEmpty()) {
//             print0(ucase ? "COLUMNS GROUP " : "columns group ");
//         } else if (x.getAdbSchema() != nullptr) {
//             print0(ucase ? "DATABASE " : "database ");
//             x.getAdbSchema().accept(this);
//         } else if (!x.getTableSources().isEmpty()) {
//             print0(ucase ? "TABLE " : "table ");
//         }

//         printAndAccept(x.getTableSources(), ", ");

//         if (!x.getAdbColumns().isEmpty()) {
//             print0("(");
//             printAndAccept(x.getAdbColumns(), ",");
//             print0(")");
//             if (x.getAdbWhere() != nullptr) {
//                 println();
//                 print0(ucase ? " WHERE " : " WHERE ");
//                 printExpr(x.getAdbWhere());
//             }
//         } else if (!x.getAdbColumnsGroup().isEmpty()) {
//             print0("(");
//             printAndAccept(x.getAdbColumnsGroup(), ",");
//             print0(")");
//             if (x.getAdbWhere() != nullptr) {
//                 println();
//                 print0(ucase ? " WHERE " : " WHERE ");
//                 printExpr(x.getAdbWhere());
//             }
//         } else if (!x.getTableSources().isEmpty()) {
//             if (x.getAdbWhere() != nullptr) {
//                 println();
//                 print0(ucase ? " WHERE " : " WHERE ");
//                 printExpr(x.getAdbWhere());
//             }
//         }

//         SQLPartitionRef partition = x.getPartition();
//         if (partition != nullptr) {
//             print(' ');
//             partition.accept(this);
//         }

//         if (x.isComputeStatistics()) {
//             print0(ucase ? " COMPUTE STATISTICS" : " compute statistics");
//         }

//         if (x.isForColums()) {
//             print0(ucase ? " FOR COLUMNS" : " for columns");
//         }

//         if (x.isCacheMetadata()) {
//             print0(ucase ? " CACHE METADATA" : " cache metadata");
//         }

//         if (x.isNoscan()) {
//             print0(ucase ? " NOSCAN" : " noscan");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlOptimizeStatement x) {
//         print0(ucase ? "OPTIMIZE " : "optimize ");
//         if (x.isNoWriteToBinlog()) {
//             print0(ucase ? "NO_WRITE_TO_BINLOG " : "No_write_to_binlog ");
//         }

//         if (x.isLocal()) {
//             print0(ucase ? "LOCAL " : "local ");
//         }

//         print0(ucase ? "TABLE " : "table ");

//         printAndAccept(x.getTableSources(), ", ");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterUserStatement x) {
//         print0(ucase ? "ALTER USER" : "alter user");

//         if (x.isIfExists()) {
//             print0(ucase ? " IF EXISTS" : " if exists");
//         }

//         for (int i = 0; i < x.getAlterUsers().size(); i++) {
//             if (i != 0) {
//                 print(',');
//             }

//             MySqlAlterUserStatement.AlterUser alterUser = x.getAlterUsers().get(i);
//             print(' ');
//             alterUser.getUser().accept(this);

//             if (alterUser.getAuthOption() != nullptr) {
//                 print(" IDENTIFIED BY ");
//                 SQLCharExpr authString = alterUser.getAuthOption().getAuthString();
//                 authString.accept(this);
//             }
//         }

//         MySqlAlterUserStatement.PasswordOption passwordOption = x.getPasswordOption();
//         if (passwordOption != nullptr) {
//             switch (passwordOption.getExpire()) {
//                 case PASSWORD_EXPIRE:
//                     print0(ucase ? " PASSWORD EXPIRE" : " password expire");
//                     break;
//                 case PASSWORD_EXPIRE_DEFAULT:
//                     print0(ucase ? " PASSWORD EXPIRE DEFAULT" : " password expire default");
//                     break;
//                 case PASSWORD_EXPIRE_NEVER:
//                     print0(ucase ? " PASSWORD EXPIRE NEVER" : " password expire never");
//                     break;
//                 case PASSWORD_EXPIRE_INTERVAL:
//                     print0(ucase ? " PASSWORD EXPIRE INTERVAL " : " password expire interval ");
//                     passwordOption.getIntervalDays().accept(this);
//                     print0(ucase ? " DAY" : " day");
//                     break;
//                 default:
//                     throw new RuntimeException("invalid password option:" + passwordOption);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLSetStatement x) {
//         BOOL_ptr printSet = x.getAttribute("parser.set") == Boolean.TRUE || DbType::oracle != dbType;
//         if (printSet) {
//             print0(ucase ? "SET " : "set ");
//         }
//         SQLSetStatement.Option option = x.getOption();
//         if (option != nullptr) {
//             print(option.name());
//             print(' ');
//         }

//         if (option == SQLSetStatement.Option.PASSWORD) {
//             print0("FOR ");
//         }

//         printAndAccept(x.getItems(), ", ");

//         if (x.getHints() != nullptr && x.getHints().size() > 0) {
//             print(' ');
//             printAndAccept(x.getHints(), " ");
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlHintStatement x) {
//         List<SQLCommentHint> hints = x.getHints();

//         for (SQLCommentHint hint : hints) {
//             hint.accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlOrderingExpr x) {
//         x.getExpr().accept(this);
//         if (x.getType() != nullptr) {
//             print(' ');
//             print0(ucase ? x.getType().name : x.getType().nameLCase);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLBlockStatement x) {
//         SQLObject parent = x.getParent();
//         string_ptr  labelName = x.getLabelName();

//         if (labelName != nullptr && !labelName.equals("")) {
//             print0(labelName);
//             print0(": ");
//         }

//         List<SQLParameter> parameters = x.getParameters();
//         if (!parameters.isEmpty()) {
//             this->indentCount++;
//             if (parent instanceof SQLCreateProcedureStatement) {
//                 printIndent();
//             }
//             if (!(parent instanceof SQLCreateProcedureStatement)) {
//                 print0(ucase ? "DECLARE" : "declare");
//                 println();
//             }

//             for (int i = 0, size = parameters.size(); i < size; ++i) {
//                 if (i != 0) {
//                     println();
//                 }
//                 SQLParameter param = parameters.get(i);
//                 visit(param);
//                 print(';');
//             }

//             this->indentCount--;
//             println();
//         }

//         print0(ucase ? "BEGIN" : "begin");
//         if (!x.isEndOfCommit()) {
//             this->indentCount++;
//         } else {
//             print(';');
//         }
//         println();
//         List<SQLStatement> statementList = x.getStatementList();
//         for (int i = 0, size = statementList.size(); i < size; ++i) {
//             if (i != 0) {
//                 println();
//             }
//             SQLStatement stmt = statementList.get(i);
//             stmt.accept(this);
//         }

//         if (!x.isEndOfCommit()) {
//             this->indentCount--;
//             println();
//             print0(ucase ? "END" : "end");
//             if (labelName != nullptr && !labelName.equals("")) {
//                 print(' ');
//                 print0(labelName);
//             }
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLIfStatement x) {
//         print0(ucase ? "IF " : "if ");
//         x.getCondition().accept(this);
//         print0(ucase ? " THEN" : " then");
//         this->indentCount++;
//         println();
//         List<SQLStatement> statements = x.getStatements();
//         for (int i = 0, size = statements.size(); i < size; ++i) {
//             SQLStatement item = statements.get(i);
//             item.accept(this);
//             if (i != size - 1) {
//                 println();
//             }
//         }
//         this->indentCount--;
//         println();
//         for (SQLIfStatement.ElseIf iterable_element : x.getElseIfList()) {
//             iterable_element.accept(this);
//         }

//         if (x.getElseItem() != nullptr) {
//             x.getElseItem().accept(this);
//         }

//         print0(ucase ? "END IF" : "end if");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLIfStatement.ElseIf x) {
//         print0(ucase ? "ELSE IF " : "else if ");
//         x.getCondition().accept(this);
//         print0(ucase ? " THEN" : " then");
//         this->indentCount++;
//         println();
//         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
//             SQLStatement item = x.getStatements().get(i);
//             item.accept(this);
//             if (i != size - 1) {
//                 println();
//             }
//         }
//         this->indentCount--;
//         println();
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLIfStatement.Else x) {
//         print0(ucase ? "ELSE " : "else ");
//         this->indentCount++;
//         println();
//         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
//             SQLStatement item = x.getStatements().get(i);
//             item.accept(this);
//             if (i != size - 1) {
//                 println();
//             }
//         }
//         this->indentCount--;
//         println();
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCaseStatement x) {
//         print0(ucase ? "CASE " : "case ");
//         if (x.getCondition() != nullptr) {
//             x.getCondition().accept(this);
//         }
//         println();
//         for (int i = 0; i < x.getWhenList().size(); i++) {
//             x.getWhenList().get(i).accept(this);
//         }
//         if (x.getElseItem() != nullptr) {
//             x.getElseItem().accept(this);
//         }
//         print0(ucase ? "END CASE" : "end case");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlDeclareStatement x) {
//         print0(ucase ? "DECLARE " : "declare ");
//         printAndAccept(x.getVarList(), ", ");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlSelectIntoStatement x) {
//         x.getSelect().accept(this);
//         print0(ucase ? " INTO " : " into ");
//         for (int i = 0; i < x.getVarList().size(); i++) {
//             x.getVarList().get(i).accept(this);
//             if (i != x.getVarList().size() - 1) {
//                 print0(", ");
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlWhenStatement x) {
//         print0(ucase ? "WHEN " : "when ");
//         x.getCondition().accept(this);
//         print0(" THEN");
//         println();
//         for (int i = 0; i < x.getStatements().size(); i++) {
//             x.getStatements().get(i).accept(this);
//             if (i != x.getStatements().size() - 1) {
//                 println();
//             }
//         }
//         println();
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLLoopStatement x) {
//         if (x.getLabelName() != nullptr && !x.getLabelName().equals("")) {
//             print0(x.getLabelName());
//             print0(": ");
//         }

//         print0(ucase ? "LOOP " : "loop ");
//         this->indentCount++;
//         println();
//         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
//             SQLStatement item = x.getStatements().get(i);
//             item.accept(this);
//             if (i != size - 1) {
//                 println();
//             }
//         }
//         this->indentCount--;
//         println();
//         print0(ucase ? "END LOOP" : "end loop");
//         if (x.getLabelName() != nullptr && !x.getLabelName().equals("")) {
//             print0(" ");
//             print0(x.getLabelName());
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlLeaveStatement x) {
//         print0(ucase ? "LEAVE " : "leave ");
//         print0(x.getLabelName());
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlIterateStatement x) {
//         print0(ucase ? "ITERATE " : "iterate ");
//         print0(x.getLabelName());
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlRepeatStatement x) {
//         // TODO Auto-generated method stub
//         if (x.getLabelName() != nullptr && !x.getLabelName().equals("")) {
//             print0(x.getLabelName());
//             print0(": ");
//         }

//         print0(ucase ? "REPEAT " : "repeat ");
//         this->indentCount++;
//         println();
//         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
//             SQLStatement item = x.getStatements().get(i);
//             item.accept(this);
//             if (i != size - 1) {
//                 println();
//             }
//         }
//         this->indentCount--;
//         println();
//         print0(ucase ? "UNTIL " : "until ");
//         x.getCondition().accept(this);
//         println();
//         print0(ucase ? "END REPEAT" : "end repeat");
//         if (x.getLabelName() != nullptr && !x.getLabelName().equals("")) {
//             print(' ');
//             print0(x.getLabelName());
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCursorDeclareStatement x) {
//         print0(ucase ? "DECLARE " : "declare ");
//         printExpr(x.getCursorName(), parameterized);
//         print0(ucase ? " CURSOR FOR" : " cursor for");
//         this->indentCount++;
//         println();
//         x.getSelect().accept(this);
//         this->indentCount--;
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlUpdateTableSource x) {
//         MySqlUpdateStatement update = x.getUpdate();
//         if (update != nullptr) {
//             update.accept0(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableAlterColumn x) {
//         print0(ucase ? "ALTER COLUMN " : "alter column ");
//         x.getColumn().accept(this);
//         if (x.getDefaultExpr() != nullptr) {
//             print0(ucase ? " SET DEFAULT " : " set default ");
//             x.getDefaultExpr().accept(this);
//         } else if (x.isDropDefault()) {
//             print0(ucase ? " DROP DEFAULT" : " drop default");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableForce x) {
//         print0(ucase ? "FORCE" : "force");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableLock x) {
//         print0(ucase ? "LOCK = " : "lock = ");
//         printExpr(x.getLockType());
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableOrderBy x) {
//         print0(ucase ? "ORDER BY " : "order by ");
//         printAndAccept(x.getColumns(), ", ");
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTableValidation x) {
//         if (x.isWithValidation()) {
//             print0(ucase ? "WITH VALIDATION" : "with validation");
//         } else {
//             print0(ucase ? "WITHOUT VALIDATION" : "without validation");
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlSubPartitionByKey x) {
//         if (x.isLinear()) {
//             print0(ucase ? "SUBPARTITION BY LINEAR KEY (" : "subpartition by linear key (");
//         } else {
//             print0(ucase ? "SUBPARTITION BY KEY (" : "subpartition by key (");
//         }
//         printAndAccept(x.getColumns(), ", ");
//         print(')');

//         if (x.getSubPartitionsCount() != nullptr) {
//             print0(ucase ? " SUBPARTITIONS " : " subpartitions ");
//             x.getSubPartitionsCount().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlSubPartitionByValue x) {
//         print0(ucase ? "SUBPARTITION BY VALUE (" : "subpartition by value (");
//         printAndAccept(x.getColumns(), ", ");
//         print(')');

//         if (x.getLifecycle() != nullptr) {
//             print0(ucase ? " LIFECYCLE " : " lifecycle ");
//             x.getLifecycle().accept(this);
//         }

//         if (x.getSubPartitionsCount() != nullptr) {
//             if ((Boolean) x.getAttribute("adb.partitons")) {
//                 print0(ucase ? " PARTITIONS " : " partitions ");
//             } else {
//                 print0(ucase ? " SUBPARTITIONS " : " subpartitions ");
//             }
//             x.getSubPartitionsCount().accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTablePartitionCount x) {
//         print0(ucase ? "PARTITIONS " : "partitons ");
//         x.getCount().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableBlockSize x) {
//         print0(ucase ? "BLOCK_SIZE " : "block_size ");
//         x.getSize().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableCompression x) {
//         print0(ucase ? "COMPRESSION = " : "compression = ");
//         x.getName().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlSubPartitionByList x) {
//         print0(ucase ? "SUBPARTITION BY LIST " : "subpartition by list ");
//         if (x.getKeys().size() > 0) {
//             if (Boolean.TRUE.equals(x.getAttribute("ads.subPartitionList"))) {
//                 print0(ucase ? "KEY (" : "key (");
//             } else {
//                 print('(');
//             }

//             printAndAccept(x.getKeys(), ",");
//             print0(") ");
//         } else {
//             if (x.getColumns().size() == 1 && Boolean.TRUE.equals(x.getAttribute("ads.subPartitionList"))) {
//                 print('(');
//             } else {
//                 print0(ucase ? "COLUMNS (" : "columns (");
//             }
//             printAndAccept(x.getColumns(), ", ");
//             print(")");
//         }

//         if (!x.getOptions().isEmpty()) {
//             println();
//             print0(ucase ? "SUBPARTITION OPTIONS (" : "subpartition options (");
//             printAndAccept(x.getOptions(), ", ");
//             print(')');
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlDeclareHandlerStatement x) {
//         string_ptr  handleType = x.getHandleType().name();

//         print0(ucase ? "DECLARE " : "declare ");
//         print0(ucase ? handleType : handleType.toLowerCase());
//         print0(ucase ? " HANDLER FOR " : " handler for ");
//         for (int i = 0; i < x.getConditionValues().size(); i++) {
//             ConditionValue cv = x.getConditionValues().get(i);
//             if (cv.getType() == ConditionType.SQLSTATE) {
//                 print0(ucase ? " SQLSTATE " : " sqlstate ");
//                 print0(cv.getValue());
//             } else if (cv.getType() == ConditionType.MYSQL_ERROR_CODE) {
//                 print0(cv.getValue());
//             } else if (cv.getType() == ConditionType.SELF) {
//                 print0(cv.getValue());
//             } else if (cv.getType() == ConditionType.SYSTEM) {
//                 print0(ucase ? cv.getValue().toUpperCase() : cv.getValue().toLowerCase());
//             }

//             if (i != x.getConditionValues().size() - 1) {
//                 print0(", ");
//             }

//         }
//         this->indentCount++;
//         println();
//         x.getSpStatement().accept(this);
//         this->indentCount--;
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlDeclareConditionStatement x) {
//         print0(ucase ? "DECLARE " : "declare ");
//         print0(x.getConditionName());
//         print0(ucase ? " CONDITION FOR " : " condition for ");

//         if (x.getConditionValue().getType() == ConditionType.SQLSTATE) {
//             print0(ucase ? "SQLSTATE " : "sqlstate ");
//             print0(x.getConditionValue().getValue());
//         } else {
//             print0(x.getConditionValue().getValue());
//         }

//         println();
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLAlterTableDropColumnItem x) {
//         for (int i = 0; i < x.getColumns().size(); ++i) {
//             if (i != 0) {
//                 print0(", ");
//             }

//             SQLName columnn = x.getColumns().get(i);

//             print0(ucase ? "DROP COLUMN " : "drop column ");
//             columnn.accept(this);

//             if (x.isCascade()) {
//                 print0(ucase ? " CASCADE" : " cascade");
//             }
//         }
//         return BOOL::FALSE;
//     }

//     /**
//      * visit procedure create node
//      */
//     // @Override
//     BOOL_ptr visit(SQLCreateProcedureStatement x) {
//         if (x.isOrReplace()) {
//             print0(ucase ? "CREATE OR REPLACE PROCEDURE " : "create or replace procedure ");
//         } else {
//             print0(ucase ? "CREATE PROCEDURE " : "create procedure ");
//         }
//         x.getName().accept(this);

//         int paramSize = x.getParameters().size();

//         print0(" (");
//         if (paramSize > 0) {
//             this->indentCount++;
//             println();

//             for (int i = 0; i < paramSize; ++i) {
//                 if (i != 0) {
//                     print0(", ");
//                     println();
//                 }
//                 SQLParameter param = x.getParameters().get(i);
//                 param.accept(this);
//             }

//             this->indentCount--;
//             println();
//         }
//         print(')');

//         if (x.getComment() != nullptr) {
//             println();
//             print(ucase ? "COMMENT " : "comment ");
//             x.getComment().accept(this);
//         }
//         if (x.isDeterministic()) {
//             println();
//             print(ucase ? "DETERMINISTIC" : "deterministic");
//         }

//         if (x.isContainsSql()) {
//             println();
//             print0(ucase ? "CONTAINS SQL" : "contains sql");
//         }

//         if (x.isLanguageSql()) {
//             println();
//             print0(ucase ? "LANGUAGE SQL" : "language sql");
//         }

//         if (x.isNoSql()) {
//             println();
//             print(ucase ? "NO SQL" : "no sql");
//         }

//         if (x.isModifiesSqlData()) {
//             println();
//             print(ucase ? "MODIFIES SQL DATA" : "modifies sql data");
//         }

//         SQLName authid = x.getAuthid();
//         if (authid != nullptr) {
//             println();
//             print(ucase ? "SQL SECURITY " : "sql security ");
//             authid.accept(this);
//         }

//         println();
//         x.getBlock().accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLCreateFunctionStatement x) {
//         print0(ucase ? "CREATE FUNCTION " : "create function ");
//         x.getName().accept(this);

//         int paramSize = x.getParameters().size();

//         if (paramSize > 0) {
//             print0(" (");
//             this->indentCount++;
//             println();

//             for (int i = 0; i < paramSize; ++i) {
//                 if (i != 0) {
//                     print0(", ");
//                     println();
//                 }
//                 SQLParameter param = x.getParameters().get(i);
//                 param.accept(this);
//             }

//             this->indentCount--;
//             println();
//             print(')');
//         }

//         println();
//         print(ucase ? "RETURNS " : "returns ");
//         x.getReturnDataType().accept(this);

//         string_ptr  comment = x.getComment();
//         if (comment != nullptr) {
//             print(ucase ? " COMMENT " : " comment ");
//             print(ucase ? comment.toUpperCase() : comment.toLowerCase());
//         }

//         if (x.isDeterministic()) {
//             print(ucase ? " DETERMINISTIC" : " deterministic");
//         }

//         string_ptr  language = x.getLanguage();
//         if (language != nullptr) {
//             print(ucase ? " LANGUAGE " : " language ");
//             print(ucase ? language.toUpperCase() : language.toLowerCase());
//         }

//         SQLStatement block = x.getBlock();

//         println();

//         block.accept(this);
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(SQLCommentStatement x) {
//         SQLCommentStatement.Type type = x.getType();

//         SQLExprTableSource on = x.getOn();
//         if (type == SQLCommentStatement.Type.TABLE) {
//             print0(ucase ? "ALTER TABLE " : "alter table ");
//             on.accept(this);
//             print0(ucase ? " COMMENT = " : " comment = ");
//             x.getComment().accept(this);
//         } else {
//             SQLPropertyExpr propertyExpr = (SQLPropertyExpr) on.getExpr();

//             SQLExpr table = propertyExpr.getOwner();
//             string_ptr  column = propertyExpr.getName();

//             print0(ucase ? "ALTER TABLE " : "alter table ");
//             printTableSourceExpr(table);
//             print0(ucase ? " MODIFY COLUMN " : " modify column ");
//             print(column);
//             print0(ucase ? " COMMENT " : " comment ");
//             x.getComment().accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlFlushStatement x) {
//         print0(ucase ? "FLUSH" : "flush");

//         if (x.isNoWriteToBinlog()) {
//             print0(ucase ? " NO_WRITE_TO_BINLOG" : " no_write_to_binlog");
//         } else if (x.isLocal()) {
//             print0(ucase ? " LOCAL" : " local");
//         }

//         if (x.isBinaryLogs()) {
//             print0(ucase ? " BINARY LOGS" : " binary logs");
//         }
//         if (x.isDesKeyFile()) {
//             print0(ucase ? " DES_KEY_FILE" : " des_key_file");
//         }
//         if (x.isEngineLogs()) {
//             print0(ucase ? " ENGINE LOGS" : " engine logs");
//         }
//         if (x.isErrorLogs()) {
//             print0(ucase ? " ERROR LOGS" : " error logs");
//         }
//         if (x.isGeneralLogs()) {
//             print0(ucase ? " GENERAL LOGS" : " general logs");
//         }
//         if (x.isHots()) {
//             print0(ucase ? " HOSTS" : " hosts");
//         }
//         if (x.isLogs()) {
//             print0(ucase ? " LOGS" : " logs");
//         }
//         if (x.isPrivileges()) {
//             print0(ucase ? " PRIVILEGES" : " privileges");
//         }
//         if (x.isOptimizerCosts()) {
//             print0(ucase ? " OPTIMIZER_COSTS" : " optimizer_costs");
//         }
//         if (x.isQueryCache()) {
//             print0(ucase ? " QUERY CACHE" : " query cache");
//         }
//         if (x.isRelayLogs()) {
//             print0(ucase ? " RELAY LOGS" : " relay logs");
//             SQLExpr channel = x.getRelayLogsForChannel();
//             if (channel != nullptr) {
//                 print(' ');
//                 channel.accept(this);
//             }
//         }
//         if (x.isSlowLogs()) {
//             print0(ucase ? " SLOW LOGS" : " slow logs");
//         }
//         if (x.isStatus()) {
//             print0(ucase ? " STATUS" : " status");
//         }
//         if (x.isUserResources()) {
//             print0(ucase ? " USER_RESOURCES" : " user_resources");
//         }

//         if (x.isTableOption()) {
//             print0(ucase ? " TABLES" : " tables");

//             List<SQLExprTableSource> tables = x.getTables();
//             if (tables != nullptr && tables.size() > 0) {
//                 print(' ');
//                 printAndAccept(tables, ", ");
//             }

//             if (x.isWithReadLock()) {
//                 print0(ucase ? " WITH READ LOCK" : " with read lock");
//             }

//             if (x.isForExport()) {
//                 print0(ucase ? " FOR EXPORT" : " for export");
//             }

//             if (x.getVersion() != nullptr) {
//                 print0(ucase ? " VERSION = " : " version = ");
//                 x.getVersion().accept(this);
//             }
//         }
//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlEventSchedule x) {
//         int cnt = 0;
//         if (x.getAt() != nullptr) {
//             print0(ucase ? "AT " : "at ");
//             printExpr(x.getAt(), parameterized);

//             cnt++;
//         }

//         if (x.getEvery() != nullptr) {
//             print0(ucase ? "EVERY " : "every ");
//             SQLIntervalExpr interval = (SQLIntervalExpr) x.getEvery();
//             printExpr(interval.getValue(), parameterized);
//             print(' ');
//             print(interval.getUnit().name());

//             cnt++;
//         }

//         if (x.getStarts() != nullptr) {
//             if (cnt > 0) {
//                 print(' ');
//             }

//             print0(ucase ? "STARTS " : "starts ");
//             printExpr(x.getStarts(), parameterized);

//             cnt++;
//         }

//         if (x.getEnds() != nullptr) {
//             if (cnt > 0) {
//                 print(' ');
//             }
//             print0(ucase ? "ENDS " : "ends ");
//             printExpr(x.getEnds(), parameterized);

//             cnt++;
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateEventStatement x) {
//         print0(ucase ? "CREATE " : "create ");

//         SQLName definer = x.getDefiner();
//         if (definer != nullptr) {
//             print0(ucase ? "DEFINER = " : "definer = ");
//         }

//         print0(ucase ? "EVENT " : "evnet ");

//         if (x.isIfNotExists()) {
//             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
//         }

//         printExpr(x.getName(), parameterized);

//         MySqlEventSchedule schedule = x.getSchedule();
//         print0(ucase ? " ON SCHEDULE " : " on schedule ");
//         schedule.accept(this);

//         Boolean enable = x.getEnable();
//         if (enable != nullptr) {
//             if (enable) {
//                 print0(ucase ? " ENABLE" : " enable");
//             } else {
//                 print0(ucase ? " DISABLE" : " disable");
//                 if (x.isDisableOnSlave()) {
//                     print0(ucase ? " ON SLAVE" : " on slave");
//                 }
//             }
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? "COMMENT " : "comment ");
//             comment.accept(this);
//         }

//         println();
//         SQLStatement body = x.getEventBody();
//         if (!(body instanceof SQLExprStatement)) {
//             print0(ucase ? "DO" : "do");
//             println();
//         }
//         body.accept(this);

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateAddLogFileGroupStatement x) {
//         print0(ucase ? "CREATE LOGFILE GROUP " : "create logfile group ");
//         x.getName().accept(this);
//         print(' ');
//         print0(ucase ? "ADD UNDOFILE " : "add undofile ");
//         printExpr(x.getAddUndoFile(), BOOL::FALSE);

//         SQLExpr initialSize = x.getInitialSize();
//         if (initialSize != nullptr) {
//             print0(ucase ? " INITIAL_SIZE " : " initial_size ");
//             printExpr(initialSize, BOOL::FALSE);
//         }

//         SQLExpr undoBufferSize = x.getUndoBufferSize();
//         if (undoBufferSize != nullptr) {
//             print0(ucase ? " UNDO_BUFFER_SIZE " : " undo_buffer_size ");
//             printExpr(undoBufferSize, BOOL::FALSE);
//         }

//         SQLExpr redoBufferSize = x.getRedoBufferSize();
//         if (redoBufferSize != nullptr) {
//             print0(ucase ? " REDO_BUFFER_SIZE " : " redo_buffer_size ");
//             printExpr(redoBufferSize, BOOL::FALSE);
//         }

//         SQLExpr nodeGroup = x.getNodeGroup();
//         if (nodeGroup != nullptr) {
//             print0(ucase ? " NODEGROUP " : " nodegroup ");
//             printExpr(nodeGroup, BOOL::FALSE);
//         }

//         if (x.isWait()) {
//             print0(ucase ? " WAIT" : " wait");
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             printExpr(comment, parameterized);
//         }

//         SQLExpr engine = x.getEngine();
//         if (engine != nullptr) {
//             print0(ucase ? " ENGINE " : " engine ");
//             printExpr(engine, parameterized);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateServerStatement x) {
//         print0(ucase ? "CREATE SERVER " : "create server ");
//         x.getName().accept(this);
//         print0(ucase ? " FOREIGN DATA WRAPPER " : " foreign data wrapper ");
//         printExpr(x.getForeignDataWrapper(), parameterized);

//         print(" OPTIONS(");
//         int cnt = 0;
//         SQLExpr host = x.getHost();
//         if (host != nullptr) {
//             print0(ucase ? "HOST " : "host ");
//             printExpr(host, parameterized);
//             cnt++;
//         }

//         SQLExpr database = x.getDatabase();
//         if (database != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "DATABASE " : "database ");
//             printExpr(database, parameterized);
//         }

//         SQLExpr user = x.getUser();
//         if (user != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "USER " : "user ");
//             printExpr(user);
//         }

//         SQLExpr password = x.getPassword();
//         if (password != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "PASSWORD " : "password ");
//             printExpr(password);
//         }

//         SQLExpr socket = x.getSocket();
//         if (socket != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "SOCKET " : "socket ");
//             printExpr(socket);
//         }

//         SQLExpr owner = x.getOwner();
//         if (owner != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "OWNER " : "owner ");
//             printExpr(owner);
//         }

//         SQLExpr port = x.getPort();
//         if (port != nullptr) {
//             if (cnt++ > 0) {
//                 print(", ");
//             }
//             print0(ucase ? "PORT " : "port ");
//             printExpr(port);
//         }
//         print(')');

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlCreateTableSpaceStatement x) {
//         print0(ucase ? "CREATE TABLESPACE " : "create tablespace ");
//         x.getName().accept(this);

//         SQLExpr addDataFile = x.getAddDataFile();
//         if (addDataFile != nullptr) {
//             print0(ucase ? " ADD DATAFILE " : " add datafile ");
//             addDataFile.accept(this);
//         }

//         SQLExpr fileBlockSize = x.getFileBlockSize();
//         if (fileBlockSize != nullptr) {
//             print0(ucase ? " FILE_BLOCK_SIZE = " : " file_block_size = ");
//             fileBlockSize.accept(this);
//         }

//         SQLExpr logFileGroup = x.getLogFileGroup();
//         if (logFileGroup != nullptr) {
//             print0(ucase ? " USE LOGFILE GROUP " : " use logfile group ");
//             logFileGroup.accept(this);
//         }

//         SQLExpr extentSize = x.getExtentSize();
//         if (extentSize != nullptr) {
//             print0(ucase ? " EXTENT_SIZE = " : " extent_size = ");
//             extentSize.accept(this);
//         }

//         SQLExpr initialSize = x.getInitialSize();
//         if (initialSize != nullptr) {
//             print0(ucase ? " INITIAL_SIZE = " : " initial_size = ");
//             initialSize.accept(this);
//         }

//         SQLExpr autoExtentSize = x.getAutoExtentSize();
//         if (autoExtentSize != nullptr) {
//             print0(ucase ? " AUTOEXTEND_SIZE = " : " autoextend_size = ");
//             autoExtentSize.accept(this);
//         }

//         SQLExpr maxSize = x.getMaxSize();
//         if (autoExtentSize != nullptr) {
//             print0(ucase ? " MAX_SIZE = " : " max_size = ");
//             maxSize.accept(this);
//         }

//         SQLExpr nodeGroup = x.getNodeGroup();
//         if (nodeGroup != nullptr) {
//             print0(ucase ? " NODEGROUP = " : " nodegroup = ");
//             nodeGroup.accept(this);
//         }

//         if (x.isWait()) {
//             print0(ucase ? " WAIT" : " wait");
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? " COMMENT " : " comment ");
//             printExpr(comment);
//         }

//         SQLExpr engine = x.getEngine();
//         if (engine != nullptr) {
//             print0(ucase ? " ENGINE " : " engine ");
//             printExpr(engine);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterEventStatement x) {
//         print0(ucase ? "ALTER " : "alter ");

//         SQLName definer = x.getDefiner();
//         if (definer != nullptr) {
//             print0(ucase ? "DEFINER = " : "definer = ");
//         }

//         print0(ucase ? "EVENT " : "evnet ");
//         printExpr(x.getName());

//         MySqlEventSchedule schedule = x.getSchedule();
//         if (schedule != nullptr) {
//             print0(ucase ? " ON SCHEDULE " : " on schedule ");
//             schedule.accept(this);
//         }

//         Boolean enable = x.getEnable();
//         if (enable != nullptr) {
//             if (enable) {
//                 print0(ucase ? " ENABLE" : " enable");
//             } else {
//                 print0(ucase ? " DISABLE" : " disable");
//                 if (x.isDisableOnSlave()) {
//                     print0(ucase ? " ON SLAVE" : " on slave");
//                 }
//             }
//         }

//         SQLExpr comment = x.getComment();
//         if (comment != nullptr) {
//             print0(ucase ? "COMMENT " : "comment ");
//             comment.accept(this);
//         }

//         SQLStatement body = x.getEventBody();
//         if (body != nullptr) {
//             println();
//             if (!(body instanceof SQLExprStatement)) {
//                 print0(ucase ? "DO" : "do");
//                 println();
//             }
//             body.accept(this);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterLogFileGroupStatement x) {
//         print0(ucase ? "ALTER LOGFILE GROUP " : "alter logfile group ");
//         x.getName().accept(this);
//         print(' ');
//         print0(ucase ? "ADD UNDOFILE " : "add undofile ");
//         printExpr(x.getAddUndoFile());

//         SQLExpr initialSize = x.getInitialSize();
//         if (initialSize != nullptr) {
//             print0(ucase ? " INITIAL_SIZE " : " initial_size ");
//             printExpr(initialSize);
//         }

//         if (x.isWait()) {
//             print0(ucase ? " WAIT" : " wait");
//         }

//         SQLExpr engine = x.getEngine();
//         if (engine != nullptr) {
//             print0(ucase ? " ENGINE " : " engine ");
//             printExpr(engine);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterServerStatement x) {
//         print0(ucase ? "ALTER SERVER " : "alter server ");
//         x.getName().accept(this);

//         print(" OPTIONS(");
//         SQLExpr user = x.getUser();
//         if (user != nullptr) {
//             print0(ucase ? "USER " : "user ");
//             printExpr(user);
//         }

//         print(')');

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlAlterTablespaceStatement x) {
//         print0(ucase ? "CREATE TABLESPACE " : "create tablespace ");
//         x.getName().accept(this);

//         SQLExpr addDataFile = x.getAddDataFile();
//         if (addDataFile != nullptr) {
//             print0(ucase ? " ADD DATAFILE " : " add datafile ");
//             addDataFile.accept(this);
//         }

//         SQLExpr initialSize = x.getInitialSize();
//         if (initialSize != nullptr) {
//             print0(ucase ? " INITIAL_SIZE = " : " initial_size = ");
//             initialSize.accept(this);
//         }

//         if (x.isWait()) {
//             print0(ucase ? " WAIT" : " wait");
//         }

//         SQLExpr engine = x.getEngine();
//         if (engine != nullptr) {
//             print0(ucase ? " ENGINE " : " engine ");
//             printExpr(engine);
//         }

//         return BOOL::FALSE;
//     }

//     // @Override
//     BOOL_ptr visit(MySqlChecksumTableStatement x) {
//         print0(ucase ? "CHECKSUM TABLE " : "checksum table ");
//         List<SQLExprTableSource> tables = x.getTables();
//         for (int i = 0; i < tables.size(); i++) {
//             if (i != 0) {
//                 print0(", ");
//             }
//             tables.get(i)
//                     .accept(this);
//         }
//         return BOOL::FALSE;
//     }

//     protected void printQuery(SQLSelectQuery x) {
//         Class<?> clazz = x.getClass();
//         if (clazz == MySqlSelectQueryBlock.class) {
//             visit((MySqlSelectQueryBlock) x);
//         } else if (clazz == SQLSelectQueryBlock.class) {
//             visit((SQLSelectQueryBlock) x);
//         } else if (clazz == SQLUnionQuery.class) {
//             visit((SQLUnionQuery) x);
//         } else {
//             x.accept(this);
//         }
//     }

void MySqlOutputVisitor::printInsertColumns(SQLExpr_list_ptr columns)
{
  int size = columns->size();
  if (size > 0)
  {
    if (size > 5)
    {
      this->indentCount++;
      print(' ');
    }
    print('(');
    auto it_columns = columns->begin();
    for (int i = 0; i < size; ++i)
    {
      if (i != 0)
      {
        if (i % 5 == 0)
        {
          println();
        }
        print0(", ");
      }

      std::advance(it_columns, i);
      SQLExpr_ptr column = *it_columns;
      if (instanceof <SQLExpr, SQLIdentifierExpr>(column))
      {
        SQLASTOutputVisitor::visit(std::dynamic_pointer_cast<SQLIdentifierExpr>(column));
      }
      else
      {
        printExpr(column, parameterized);
      }

      Object_ptr dataType = column->getAttribute("dataType");
      if (dataType != nullptr)
      {
        print(' ');
        print(dataType->getString());
      }
    }
    print(')');
    if (size > 5)
    {
      this->indentCount--;
    }
  }
}

//     // @Override
//     BOOL_ptr visit(SQLValuesTableSource x) {
//         print('(');
//         incrementIndent();
//         println();
//         print0(ucase ? "VALUES " : "values ");
//         List<SQLListExpr> values = x.getValues();
//         for (int i = 0; i < values.size(); ++i) {
//             if (i != 0) {
//                 print(", ");
//                 println();
//             }
//             SQLListExpr list = values.get(i);
//             visit(list);
//         }
//         decrementIndent();
//         println();
//         print0(")");
//         if (x.getAlias() != nullptr) {
//             print0(" AS ");
//             print0(x.getAlias());

//             if (x.getColumns().size() > 0) {
//                 print0(" (");
//                 printAndAccept(x.getColumns(), ", ");
//                 print(')');
//             }
//         }

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(SQLExternalRecordFormat x) {
//         return hiveVisit(x);
//     }

//     BOOL_ptr visit(MySqlJSONTableExpr x) {
//         print0(ucase ? "JSON_TABLE(" : "json_table(");
//         x.getExpr().accept(this);
//         print(',');
//         x.getPath().accept(this);
//         incrementIndent();
//         println();
//         print0(ucase ? "COLUMNS (" : "columns (");
//         incrementIndent();
//         println();
//         printlnAndAccept(x.getColumns(), ",");
//         decrementIndent();
//         println();
//         print(')');
//         decrementIndent();
//         println();
//         print(')');

//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(MySqlJSONTableExpr.Column x) {
//         x.getName().accept(this);

//         if (x.isOrdinality()) {
//             print0(ucase ? " FOR ORDINALITY" : " for ordinality");
//         }

//         SQLDataType dataType = x.getDataType();
//         if (dataType != nullptr) {
//             print(' ');
//             dataType.accept(this);
//         }

//         if (x.isExists()) {
//             print0(ucase ? " EXISTS" : " exists");
//         }

//         SQLExpr path = x.getPath();
//         if (path != nullptr) {
//             print0(ucase ? " PATH " : " path ");
//             path.accept(this);
//         }

//         List<MySqlJSONTableExpr.Column> nestedColumns = x.getNestedColumns();
//         if (nestedColumns.size() > 0) {
//             print0(ucase ? " COLUMNS (" : " columns (");
//             printAndAccept(nestedColumns, ", ");
//             print(')');
//         }

//         SQLExpr onEmpty = x.getOnEmpty();
//         if (onEmpty != nullptr) {
//             print(' ');
//             if (!(onEmpty instanceof SQLNullExpr || onEmpty instanceof SQLIdentifierExpr)) {
//                 print0(ucase ? "DEFAULT " : "default ");
//             }
//             onEmpty.accept(this);
//             print0(ucase ? " ON EMPTY" : " on empty");
//         }

//         SQLExpr onError = x.getOnError();
//         if (onError != nullptr) {
//             print(' ');
//             if (!(onEmpty instanceof SQLNullExpr || onEmpty instanceof SQLIdentifierExpr)) {
//                 print0(ucase ? "DEFAULT " : "default ");
//             }
//             onError.accept(this);
//             print0(ucase ? " ON ERROR" : " on error");
//         }
//         return BOOL::FALSE;
//     }

// //    BOOL_ptr visit(SQLSelectItem x) {
// //        SQLExpr expr = x.getExpr();
// //
// //        if (expr instanceof SQLIdentifierExpr) {
// //            print0(((SQLIdentifierExpr) expr).getName());
// //        } else if (expr instanceof SQLPropertyExpr) {
// //            visit((SQLPropertyExpr) expr);
// //        } else {
// //            printExpr(expr);
// //        }
// //
// //        string_ptr  alias = x.getAlias();
// //        if (alias != nullptr && alias.length() > 0) {
// //            print0(ucase ? " AS " : " as ");
// //
// //            BOOL_ptr hasSpecial = BOOL::FALSE;
// //            for (int i = 1; i < alias.length() - 1; ++i) {
// //                char ch = alias.charAt(i);
// //                if (ch == ' ' || ch == '\"' || ch == '\n') {
// //                    hasSpecial = BOOL::TRUE;
// //                }
// //            }
// //            char c0 = alias.charAt(0);
// //            if (!hasSpecial) {
// //                print0(alias);
// //            } else {
// //                print('"');
// //
// //                for (int i = 0; i < alias.length(); ++i) {
// //                    char ch = alias.charAt(i);
// //                    if (ch == '\"') {
// //                        print('\\');
// //                        print(ch);
// //                    } else if (ch == '\n') {
// //                        print0("\\n");
// //                    } else {
// //                        print(ch);
// //                    }
// //                }
// //
// //                print('"');
// //            }
// //        }
// //        return BOOL::FALSE;
// //    }

//     BOOL_ptr visit(MysqlAlterTableAlterCheck x) {
//         print0(ucase ? "ALTER CONSTRAINT " : "alter constraint ");

//         SQLName name = x.getName();
//         if (name != nullptr) {
//             name.accept(this);
//             print(' ');
//         }

//         Boolean enforced = x.getEnforced();
//         if (enforced != nullptr) {
//             if (enforced) {
//                 print0(ucase ? " ENFORCED" : " enforced");
//             } else {
//                 print0(ucase ? " NOT ENFORCED" : " not enforced");
//             }
//         }
//         return BOOL::FALSE;
//     }

//     BOOL_ptr visit(MySqlXAStatement x) {
//         print0(ucase ? "XA " : "xa ");

//         MySqlXAStatement.XAType type = x.getType();
//         print0(ucase ? type.name() : type.name().toLowerCase());
//         SQLExpr id = x.getId();
//         if (id != nullptr) {
//             print(' ');
//             printExpr(id);
//         }
//         return BOOL::FALSE;
//     }
